宏任務與微任務

轉自前端

https://juejin.im/post/59e85eebf265da430d571f89

 

導圖要表達的內容用文字來表述的話:node

同步和異步任務分別進入不一樣的執行"場所",同步的進入主線程,異步的進入Event Table並註冊函數。
當指定的事情完成時,Event Table會將這個函數移入Event Queue。
主線程內的任務執行完畢爲空,會去Event Queue讀取對應的函數,進入主線程執行。
上述過程會不斷重複,也就是常說的Event Loop(事件循環)。
  • macro-task(宏任務):

 

包括總體代碼script,setTimeout,setInterval

 

  • micro-task(微任務):
Promise.then,Promise.catch, process.nextTick
注意:
1.
promise是當即執行的,它建立的時候就會執行,不存在將promise推入微任務中的說法; resolve()是用來表示promise的狀態爲fullfilled,至關於只是定義了一個有狀態的Promise,可是並無調用它; promise調用then的前提是promise的狀態爲fullfilled; 只有promise調用then的時候,then裏面的函數纔會被推入微任務中

2.
  script標籤中的console.log()會當即執行

分析:promise

console.log('1');

setTimeout(function() {
    console.log('2');
    process.nextTick(function() {
        console.log('3');
    })
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})
process.nextTick(function() { console.log(
'6'); })
new Promise(function(resolve) { console.log('7'); resolve(); }).then(function() { console.log('8') }) setTimeout(function() { console.log('9'); process.nextTick(function() { console.log('10'); }) new Promise(function(resolve) { console.log('11'); resolve(); }).then(function() { console.log('12') }) })

 

第一輪事件循環流程分析以下:異步

  • 總體script做爲第一個宏任務進入主線程,遇到console.log,輸出1。
  • 遇到setTimeout,其回調函數被分發到宏任務Event Queue中。咱們暫且記爲setTimeout1
  • 遇到process.nextTick(),其回調函數被分發到微任務Event Queue中。咱們記爲process1
  • 遇到Promisenew Promise直接執行,輸出7。then被分發到微任務Event Queue中。咱們記爲then1
  • 又遇到了setTimeout,其回調函數被分發到宏任務Event Queue中,咱們記爲setTimeout2
宏任務Event Queue 微任務Event Queue
setTimeout1 process1
setTimeout2 then1
  • 上表是第一輪事件循環宏任務結束時各Event Queue的狀況,此時已經輸出了1和7。函數

  • 咱們發現了process1then1兩個微任務。oop

  • 執行process1,輸出6。
  • 執行then1,輸出8。

好了,第一輪事件循環正式結束,這一輪的結果是輸出1,7,6,8。post

那麼第二輪事件循環從setTimeout1宏任務開始:spa

  • 首先輸出2。接下來遇到了process.nextTick(),一樣將其分發到微任務Event Queue中,記爲process2new Promise當即執行輸出4,then也分發到微任務Event Queue中,記爲then2
宏任務Event Queue 微任務Event Queue
setTimeout2 process2
  then2
  • 第二輪事件循環宏任務結束,咱們發現有process2then2兩個微任務能夠執行。
  • 輸出3。
  • 輸出5。
  • 第二輪事件循環結束,第二輪輸出2,4,3,5。
  • 第三輪事件循環開始,此時只剩setTimeout2了,執行。
  • 直接輸出9。
  • process.nextTick()分發到微任務Event Queue中。記爲process3
  • 直接執行new Promise,輸出11。
  • then分發到微任務Event Queue中,記爲then3
宏任務Event Queue 微任務Event Queue
  process3
  then3
  • 第三輪事件循環宏任務執行結束,執行兩個微任務process3then3
  • 輸出10。
  • 輸出12。
  • 第三輪事件循環結束,第三輪輸出9,11,10,12。

整段代碼,共進行了三次事件循環,完整的輸出爲1,7,6,8,2,4,3,5,9,11,10,12。
(請注意,node環境下的事件監聽依賴libuv與前端環境不徹底相同,輸出順序可能會有偏差)線程

相關文章
相關標籤/搜索