Javascript的異步編程的理解

在單線程的javascript編程來說,所有的任務(wù)分為兩種,一種是同步任務(wù)(synchronous),

另一種是異步任務(wù)(asynchronous)。同步任務(wù)指的是,在主線程上排隊(duì)執(zhí)行的任務(wù),只有前一個(gè)任務(wù)執(zhí)行完畢,

才能執(zhí)行后一個(gè)任務(wù),異步任務(wù)指的是,不進(jìn)入主線程,而進(jìn)入"任務(wù)隊(duì)列"(task queue)的任務(wù),

只有"任務(wù)隊(duì)列"通知主線程,某個(gè)異步任務(wù)就可以執(zhí)行了,該任務(wù)才會(huì)進(jìn)入主線程執(zhí)行瓦糟。

具體來說就是:

1.所有的同步任務(wù)都在主線程上執(zhí)行,形成一個(gè)執(zhí)行棧(execution context stack)

2.主線程之外,還存在一個(gè)"任務(wù)隊(duì)列"(task queue),只要異步任務(wù)有了運(yùn)行結(jié)果,就在"任務(wù)隊(duì)列"之中放置一個(gè)事件

3.一旦"執(zhí)行棧"中的所有同步任務(wù)執(zhí)行完畢,系統(tǒng)就會(huì)讀取"任務(wù)隊(duì)列",看看里面有哪些事件筒愚。

那些對(duì)應(yīng)的異步任務(wù),于是結(jié)束等待狀態(tài),進(jìn)入執(zhí)行棧,開始執(zhí)行

4.主線程不斷重復(fù)上面的第三步

只要主線程空了,就會(huì)讀取"任務(wù)隊(duì)列",這就是javascript的運(yùn)行機(jī)制,這個(gè)過程會(huì)不斷重復(fù)

Event Loop 是上面的第三步 這個(gè)過程是不斷重復(fù)的

可以參考:

http://www.ruanyifeng.com/blog/2014/10/event-loop.html

setTimeout(function(){console.log(1);}, 0);

console.log(2);

上面代碼的執(zhí)行結(jié)果總是2,1,因?yàn)橹挥性趫?zhí)行完第二行以后,

系統(tǒng)才會(huì)去執(zhí)行"任務(wù)隊(duì)列"中的回調(diào)函數(shù)

需要注意的是菩浙,setTimeout()只是將事件插入了"任務(wù)隊(duì)列"巢掺,必須等到當(dāng)前代碼(執(zhí)行棧)執(zhí)行完,

主線程才會(huì)去執(zhí)行它指定的回調(diào)函數(shù)劲蜻。要是當(dāng)前代碼耗時(shí)很長陆淀,有可能要等很久,

所以并沒有辦法保證先嬉,回調(diào)函數(shù)一定會(huì)在setTimeout()指定的時(shí)間執(zhí)行轧苫。

javascript寫手如果稱一個(gè)函數(shù)為"異步的",其意思是這個(gè)函數(shù)會(huì)導(dǎo)致將來再運(yùn)行另一個(gè)函數(shù)

后者取自于事件隊(duì)列(若后面這個(gè)函數(shù)是作為參數(shù)傳遞給前者的,則成為前者的回調(diào)函數(shù))


理解了異步任務(wù)的任務(wù)隊(duì)列后:

demo1:

var ajaxRequest=new XMLHttpRequest();

ajaxRequest.open("GET","data/activity.json",true)

ajaxRequest.send(null) ? ? ?

while(ajaxRequest.readyState ===1){ //當(dāng)有發(fā)出open請(qǐng)求 readyState為1

alert(1) //無限彈1,當(dāng)然永遠(yuǎn)也輪不懂send運(yùn)行

}

//ajaxRequest.readyState ===4也是不行的 因?yàn)楫?dāng)readyState===4時(shí),while已經(jīng)執(zhí)行完了

//所以需要引入事件監(jiān)聽(例如onreadystatechange)把異步的任務(wù)返回主線程的任務(wù)隊(duì)列

//ajaxRequest.send(null) //異步任務(wù)在同步任務(wù)全部完成后執(zhí)行 ? 即send真正的執(zhí)行位置

readyState,onreadystatechange都是要依賴異步的send函數(shù)發(fā)回來的狀態(tài),不過時(shí)間微秒級(jí)

onreadystatechange對(duì)應(yīng)的函數(shù)相當(dāng)于send的回調(diào)函數(shù),要在send執(zhí)行后才能執(zhí)行

(這就是事件監(jiān)聽的用處:返回任務(wù)隊(duì)列)

demo2:

var a=10;

var ajaxRequest=new XMLHttpRequest();

ajaxRequest.open("GET","data/activity.json",true)

ajaxRequest.send(null)

ajaxRequest.onreadystatechange=function(){? //異步事件隊(duì)列返同步任務(wù)對(duì)的事件監(jiān)聽

console.log("我是ajax請(qǐng)求回來觸發(fā)事件監(jiān)聽的標(biāo)志")

console.log("異步任務(wù)ajax請(qǐng)求回來觸發(fā)事件監(jiān)聽的時(shí)刻",new Date().getTime()-c)

}

setTimeout(function(){

console.log("同步任務(wù)執(zhí)行完0.004秒后立刻執(zhí)行,setTimeout函數(shù)實(shí)際的延時(shí)時(shí)間會(huì)有偏差")

console.log("異步任務(wù)setTimeout執(zhí)行的時(shí)刻",new Date().getTime()-c)

a++

console.log("異步隊(duì)列返回同步隊(duì)列,a="+a);

},0)

console.log("同步任務(wù)","a="+a)

var four = new Date();

var c = four.getTime()

for(var i=0;i<1000000000;i++){

if(i === 0){

console.log("同步任務(wù),i=0時(shí)執(zhí)行的時(shí)刻:",new Date().getTime()-c)

}

if(i === (1000000000-1)){

console.log("同步任務(wù),i=999999時(shí)執(zhí)行的時(shí)刻:",new Date().getTime()-c)

console.log("ajax的send()是在我執(zhí)行完它才開始請(qǐng)求的,并不是我在進(jìn)行的同時(shí)它也在請(qǐng)求,所以send()函數(shù)放在腳本的結(jié)尾和現(xiàn)在是一樣的效果")

}

}

//ajaxRequest.send(null) ? ? ? ? ? //實(shí)際上異步的send函數(shù)是在主線程空了再執(zhí)行 ?也就是腳本的結(jié)尾

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市坝初,隨后出現(xiàn)的幾起案子浸剩,更是在濱河造成了極大的恐慌钾军,老刑警劉巖鳄袍,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異吏恭,居然都是意外死亡拗小,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門樱哼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來哀九,“玉大人剿配,你說我怎么就攤上這事≡氖” “怎么了呼胚?”我有些...
    開封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長息裸。 經(jīng)常有香客問我蝇更,道長,這世上最難降的妖魔是什么呼盆? 我笑而不...
    開封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任年扩,我火速辦了婚禮,結(jié)果婚禮上访圃,老公的妹妹穿的比我還像新娘厨幻。我一直安慰自己,他們只是感情好腿时,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開白布况脆。 她就那樣靜靜地躺著,像睡著了一般批糟。 火紅的嫁衣襯著肌膚如雪漠另。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天跃赚,我揣著相機(jī)與錄音笆搓,去河邊找鬼。 笑死纬傲,一個(gè)胖子當(dāng)著我的面吹牛满败,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播叹括,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼算墨,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了汁雷?” 一聲冷哼從身側(cè)響起净嘀,我...
    開封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎侠讯,沒想到半個(gè)月后挖藏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡厢漩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年膜眠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宵膨,死狀恐怖架谎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情辟躏,我是刑警寧澤谷扣,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站捎琐,受9級(jí)特大地震影響抑钟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜野哭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一在塔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拨黔,春花似錦蛔溃、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至零截,卻和暖如春麸塞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背涧衙。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來泰國打工哪工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人弧哎。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓雁比,卻偏偏與公主長得像,于是被迫代替她去往敵國和親撤嫩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子偎捎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容