Event Loop、 宏任務(wù)和微任務(wù)

本文將介紹我自己對JS Event Loop宏任務(wù)、微任務(wù)的理解。
二話不說先上圖:

接下來將會針對此圖講解什么是Event Loop 什么事宏任務(wù)和微任務(wù)(其實聰明的你們通過圖大體也能了解的是吧~),再此之前先簡單介紹幾個概念。

為何js是單線程

JavaScript的單線程,與它的用途有關(guān)。作為瀏覽器腳本語言,JavaScript的主要用途是與用戶互動,以及操作DOM。這決定了它只能是單線程,否則會帶來很復(fù)雜的同步問題。比如,假定JavaScript同時有兩個線程,一個線程在某個DOM節(jié)點上添加內(nèi)容,另一個線程刪除了這個節(jié)點,這時瀏覽器應(yīng)該以哪個線程為準?

所以,為了避免復(fù)雜性,從一誕生,JavaScript就是單線程,這已經(jīng)成了這門語言的核心特征,將來也不會改變。

為了利用多核CPU的計算能力,HTML5提出 Web Worker 標準,允許JavaScript腳本創(chuàng)建多個線程,但是子線程完全受主線程控制,且不得操作DOM。所以,這個新標準并沒有改變JavaScript單線程的本質(zhì)。(此段來自阮老師)

概念

  • 同步任務(wù):在主線程上排隊執(zhí)行的任務(wù),只有前一個任務(wù)執(zhí)行完畢,才能執(zhí)行后一個任務(wù)。
  • 異步任務(wù):不進入主線程、而進入任務(wù)隊列(Task Queue)的任務(wù)。
  • 任務(wù)隊列:是一個事件的隊列(也可以理解成消息的隊列),IO設(shè)備完成一項任務(wù),就在"任務(wù)隊列"中添加一個事件,表示相關(guān)的異步任務(wù)可以進入"執(zhí)行棧"了。主線程讀取"任務(wù)隊列",就是讀取里面有哪些事件。

詳解圖示

  1. 當一段代碼在主線程執(zhí)行時,會有同步任務(wù)和異步任務(wù),異步任務(wù)會判斷是微任務(wù)還是宏任務(wù),進行不同處理。然后繼續(xù)執(zhí)行當前主線程內(nèi)的代碼,直到結(jié)束。此段主線程執(zhí)行的的為宏任務(wù)
  2. 接著上面的判斷,宏任務(wù)的異步操作會先進入Event Table執(zhí)行,然后當執(zhí)行結(jié)束會把回調(diào)函數(shù)推入到Event Queue ,然后等待主線程的結(jié)束。對于微任務(wù)的異步會推入到另外一個Event Queue ,等待主線程的結(jié)束。
  3. 當主線程結(jié)束后,先執(zhí)行所有的微任務(wù),然后執(zhí)行把宏任務(wù)的任務(wù)隊列(Event Queue)中的event拉到主線程執(zhí)行。
  4. 一直循環(huán)前面的操作。至此你應(yīng)該懂的EventLoop了。
    備注:如果在執(zhí)行 microtask(微任務(wù)) 的過程中,又產(chǎn)生了microtask,那么會加入到隊列的末尾,也會在這個周期被調(diào)用執(zhí)行。

舉個例子??

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

new Promise(function(resolve) {
  console.log('promise 1');
  resolve();
  console.log('promise 2')
}).then(function() {
    console.log('promise then');
})

console.log('1');

輸出結(jié)果:promise 1 、promise 2 、1 、promise then 、setTimeout
解釋

  • 這段代碼作為宏任務(wù),進入主線程。
  • 先遇到setTimeout,則進入Event Table執(zhí)行并注冊,然后將其回調(diào)函數(shù)發(fā)到宏任務(wù)Event Queue。
  • 接下來遇到了Promise,new Promise立即執(zhí)行,then函數(shù)分發(fā)到微任務(wù)Event Queue。里面的console.log(),立即執(zhí)行。
  • 繼續(xù),遇到console.log(),立即執(zhí)行。
  • 至此這個主線程的宏任務(wù)執(zhí)行結(jié)束,接著查找微任務(wù),發(fā)現(xiàn)then的回調(diào)然后執(zhí)行。
  • 第一輪事件循環(huán)結(jié)束了,我們開始第二輪循環(huán),從宏任務(wù)Event Queue開始執(zhí)行。即宏任務(wù)Event Queue中setTimeout對應(yīng)的回調(diào)函數(shù),立即執(zhí)行。
  • END。

為何會有宏任務(wù)和微任務(wù)的說法。

eventloop中處理微任務(wù)和宏任務(wù)的邏輯也是不同廠商按照規(guī)范實現(xiàn)的 jsvm。

補充幾個宏任務(wù)和微任務(wù)

宏任務(wù) 瀏覽器 Node
setTimeout
setInterval
setImmediate x
requestAnimationFrame x
微任務(wù) 瀏覽器 Node
process.nextTick x
MutationObserver x
Promise.then catch finally
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容