js事件循環(huán)機(jī)制

1. 什么是事件循環(huán)屹逛?

js引擎并不是獨(dú)立運(yùn)行的深啤,它運(yùn)行在宿主環(huán)境中拗馒,對多數(shù)開發(fā)者來說通常就是web瀏覽器。經(jīng)過最近幾年的發(fā)展溯街,js已經(jīng)超出了瀏覽器的范圍诱桂,進(jìn)入了其他環(huán)境。
所以這些環(huán)境都有一個(gè)共同“點(diǎn)”(thread,也指線程),即它們都提供了一種機(jī)制來處理程序中多個(gè)塊的執(zhí)行呈昔,且執(zhí)行每塊時(shí)調(diào)用js引擎挥等,這種機(jī)制被稱為事件循環(huán)

2. event loop它最主要是分三部分:主線程堤尾、宏隊(duì)列(macrotask)肝劲、微隊(duì)列(microtask)

js的任務(wù)隊(duì)列分為同步任務(wù)和異步任務(wù),所有的同步任務(wù)都是在主線程里執(zhí)行的,異步任務(wù)可能會在macrotask或者microtask里面辞槐。

3. 主線程

就是訪問到的script標(biāo)簽里面包含的內(nèi)容掷漱,或者是直接訪問某一個(gè)js文件的時(shí)候,里面的可以在當(dāng)前作用域直接執(zhí)行的所有內(nèi)容(執(zhí)行的方法榄檬、new出來的對象)

4. js引擎的兩大特點(diǎn):單線程和非阻塞

  • 單線程:只有一個(gè)主線程來處理任務(wù)卜范。
  • 非阻塞:當(dāng)執(zhí)行異步任務(wù)時(shí),不必等到結(jié)果返回鹿榜,主線程會掛起(pending)這個(gè)任務(wù)海雪,然后根據(jù)一定規(guī)則執(zhí)行回調(diào)函數(shù)(事件循環(huán)機(jī)制)。

JS通常是非阻塞的舱殿,除了某些特殊情況奥裸,JS會停止代碼執(zhí)行:
alert, confirm, prompt(除了Opera)。
“頁面上的程序正忙”的系統(tǒng)對話框彈出沪袭。

5. 任務(wù)分類:同步和異步

  • 同步任務(wù)(macrotask ):會立即執(zhí)行的任務(wù)刺彩。
  • 異步任務(wù)(microtask ):不會立即執(zhí)行的任務(wù),可細(xì)分為一下兩種:宏任務(wù)和微任務(wù)枝恋。

--宏任務(wù):script, setTimeout, setInterval, setImmeditate, T/O, UI rendering
-- 微任務(wù):process, nextTick, promise.then(), object.observe, MutationObserver

6. 執(zhí)行順序

1、先執(zhí)行主線程

2嗡害、遇到宏隊(duì)列(macrotask)放到宏隊(duì)列(macrotask)

3焚碌、遇到微隊(duì)列(microtask)放到微隊(duì)列(microtask)

4、主線程執(zhí)行完畢

5霸妹、執(zhí)行微隊(duì)列(microtask)十电,微隊(duì)列(microtask)執(zhí)行完畢

6、執(zhí)行一次宏隊(duì)列(macrotask)中的一個(gè)任務(wù)叹螟,執(zhí)行完畢

7鹃骂、執(zhí)行微隊(duì)列(microtask),執(zhí)行完畢

8罢绽、依次循環(huán)畏线。。良价。

7. 執(zhí)行棧和任務(wù)隊(duì)列

占內(nèi)存和堆內(nèi)存
棧內(nèi)存保存著JS的變量和指向堆內(nèi)存中對象的指針寝殴,堆內(nèi)存保存著對象。

  • 執(zhí)行棧:

后進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)明垢,當(dāng)函數(shù)被調(diào)用時(shí)添加到執(zhí)行棧頂部蚣常,從棧頂移出。當(dāng)一個(gè)任務(wù)為同步任務(wù)時(shí)痊银,則會被立即執(zhí)行抵蚊,執(zhí)行完移出;如果是異步任務(wù),則會交給異步處理模塊處理贞绳,當(dāng)異步任務(wù)回調(diào)達(dá)到觸發(fā)條件時(shí)谷醉,會將回調(diào)函數(shù)添加到任務(wù)隊(duì)列中,如果是宏任務(wù)熔酷,則添加到宏任務(wù)隊(duì)列中孤紧,如果是為微任務(wù),則添加到微任務(wù)隊(duì)列中拒秘。

  • 任務(wù)隊(duì)列:

任務(wù)隊(duì)列讀取任務(wù)的順序?yàn)楹耆蝿?wù)-微任務(wù)(微任務(wù)隊(duì)列全部執(zhí)行結(jié)束才進(jìn)入到下一輪宏任務(wù))-宏任務(wù)-微任務(wù)的順序号显;當(dāng)執(zhí)行棧中的任務(wù)全部完成之后會從事件隊(duì)列中讀取一個(gè)任務(wù)添加到執(zhí)行棧。一個(gè)任務(wù)隊(duì)列中可以有多個(gè)宏任務(wù)隊(duì)列躺酒,但只能有一個(gè)微任務(wù)隊(duì)列押蚤。

圖示:
image.png
  • 引入微任務(wù)隊(duì)列后,事實(shí)上事件循環(huán)執(zhí)行的流程是這樣的:
  1. 一開始把一整段的JS腳本作為第一個(gè)宏任務(wù)執(zhí)行
  2. 在執(zhí)行過程中羹应,同步代碼則直接運(yùn)行揽碘,過程中存在宏任務(wù)則進(jìn)入到宏任務(wù)隊(duì)列,微任務(wù)在微任務(wù)隊(duì)列中入列园匹。
  3. 在當(dāng)前宏任務(wù)執(zhí)行完成后雳刺,檢查微任務(wù)隊(duì)列,若存在微任務(wù)則按序全部執(zhí)行完畢裸违。
  4. 繼續(xù)檢查宏任務(wù)隊(duì)列掖桦,執(zhí)行下一個(gè)宏任務(wù),如此反復(fù)供汛。

理解了原理后枪汪,可以根據(jù)這個(gè)步驟來多看幾個(gè)例子,嘗試寫出打印的結(jié)果怔昨。

Promise.resolve().then(()=>{
  console.log('Promise1')  
  setTimeout(()=>{
    console.log('setTimeout2')
  },0)
});
setTimeout(()=>{
  console.log('setTimeout1')
  Promise.resolve().then(()=>{
    console.log('Promise2')    
  })
},0);
console.log('start');

// start
// Promise1
// setTimeout1
// Promise2
// setTimeout2
  • 有個(gè)小 tip:從規(guī)范來看雀久,microtask (微任務(wù))優(yōu)先于 macrotask(宏任務(wù)) 執(zhí)行,所以如果有需要優(yōu)先執(zhí)行的邏輯趁舀,放入microtask 隊(duì)列會比 task 更早的被執(zhí)行赖捌。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市矮烹,隨后出現(xiàn)的幾起案子巡蘸,更是在濱河造成了極大的恐慌,老刑警劉巖擂送,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悦荒,死亡現(xiàn)場離奇詭異,居然都是意外死亡嘹吨,警方通過查閱死者的電腦和手機(jī)搬味,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人碰纬,你說我怎么就攤上這事萍聊。” “怎么了悦析?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵寿桨,是天一觀的道長。 經(jīng)常有香客問我强戴,道長亭螟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任骑歹,我火速辦了婚禮预烙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘道媚。我一直安慰自己扁掸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布最域。 她就那樣靜靜地躺著谴分,像睡著了一般。 火紅的嫁衣襯著肌膚如雪镀脂。 梳的紋絲不亂的頭發(fā)上牺蹄,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機(jī)與錄音狗热,去河邊找鬼。 笑死虑省,一個(gè)胖子當(dāng)著我的面吹牛匿刮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播探颈,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼熟丸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了伪节?” 一聲冷哼從身側(cè)響起光羞,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎怀大,沒想到半個(gè)月后纱兑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡化借,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年潜慎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡铐炫,死狀恐怖垒手,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情倒信,我是刑警寧澤科贬,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站鳖悠,受9級特大地震影響榜掌,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜竞穷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一唐责、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瘾带,春花似錦鼠哥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至允蚣,卻和暖如春于颖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嚷兔。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工森渐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人冒晰。 一個(gè)月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓同衣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親壶运。 傳聞我的和親對象是個(gè)殘疾皇子耐齐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

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