node事件迴圈學習筆記

一顆白菜發表於2019-02-13
  • setTimeout(() => console.log(1));
    setImmediate(() => console.log(2));
    process.nextTick(() => console.log(3));
    Promise.resolve().then(() => console.log(4));
    (() => console.log(5))();
    複製程式碼

    執行結果:

    5
    3
    4
    1
    2
    複製程式碼

node事件分 同步、非同步,由於JS的單執行緒原理,非同步事件的處理方式依靠 事件迴圈。

  • 非同步事件分為:微事件/巨集事件
  • 微事件包括:
    • process.nextTick
    • Promise.then
  • 巨集事件包括:
    • setTimeout/setInterval
    • setImmediate
    • I/O callback

不同的非同步事件,迴圈規則也不同。


巨集事件迴圈

  1. timers階段:setTimeout/setInterval的回撥函式執行階段
  2. I/O callbacks階段:未解決的回撥執行執行
  3. poll階段:輪詢階段。接受新的I/O回撥,並將其加入輪詢列隊中進行先進先出的順序執行。
    • 若該階段事件列隊為空,檢查check階段是否有事件列隊,有則順序執行。同時也會檢查是否有定時器到達閾值,如果有則迴圈繞到timers階段時執行。如果沒有其他非同步任務要處理會一直停留在該階段等待 I/O 結果返回。
    • 若該階段的事件列隊不為空,則將事件列隊中的事件執行完直到為空,或直到記憶體溢位
  4. check階段:執行setImmediate()的回撥函式
  5. close callbacks:執行關閉請求的回撥函式 .on('close', callback)

微事件迴圈

  1. process.nextTick
  2. Promise.then

在同一次迴圈中process.nextTick總要比Promise.then先執行

迴圈原則

  • 只有前一個階段的事件佇列全部清空以後,才會執行下一個階段的事件佇列
  • 進入到下一個階段的事件列隊之前,會先執行微事件列隊直到為空。
  • 同一次迴圈中,微事件的執行總是優先於巨集事件

事件執行順序:

  1. 同步事件
  2. 發出非同步請求
  3. 規劃定時器生效的時間
  4. process.nextTick
  5. Promise.then
  6. 事件迴圈

圖解

筆者自畫,理解不當之處,敬請糾正,感激不盡

image

終極挑戰

setTimeout(() => {
  process.nextTick(() => {
    console.log(1)
    process.nextTick(() => console.log(2))
  });
  console.log(3)
  setTimeout(() => { console.log(4)})
  setImmediate(() => console.log(5));
});
setTimeout(() => {
  process.nextTick(() => console.log(6));
  Promise.resolve(7).then(res=>console.log(res))
  console.log(8)
});
(() => console.log(9))();
setImmediate(() => console.log(10));
複製程式碼

你答對了嗎?

9
3
8
1
6
2
7
10
5
4
複製程式碼

參考連結

Node 定時器詳解——阮一峰

Node.js event loop workflow & lifecycle in low level

相關文章