Try   HackMD

Node.js event queue

Node.js 當 main thread 執行結束後會進入 event queue 迴圈中。每次 event queue 迴圈中有下面 6 個階段,每個階段會執行它相應的 queue 內的 task,當它的 queue 內的 task 執行完畢後會執行完所有 porcess.nextTick() 放入 nextTickQueue
中的 task,接著再執行完 Promise 放入 micro task queue 中的 task,並且會等到 nextTickQueuemicro task queue 全部執行完畢後才會進入下個階段。
所以如果 Promise resolve 中會產生新的 Promiseprocess.nextTick 會呼叫新的 process.nextTickmicro task queue 階段就會一直執行下去而卡住 event queue 讓程式無法回應 request。
比方:

const f = () => { process.nextTick(() => console.log(1)); Promise.resolve().then(() => console.log(2)); }; f(); Promise.resolve().then(f);

會印出 1221,它的執行狀況是:

  1. main thread 執行 f()
  2. f() 內的 process.nextTick(() => console.log(1));console.log(1) 放入 nextTickQueue
  3. f() 內的 Promise.resolve().then(() => console.log(2));console.log(2) 放入 micro task queue
  4. main thread 執行 Promise.resolve().then(f);f() 放入 micro task queue
  5. main thread 結束,開始 even queue
  6. timer 階段沒有 timer 所以結束
  7. 開始執行 nextTickQueue 中的 task,印出 1,之後 nextTickQueue 沒有 task
  8. 開始執行 micro task queue 印出 2
  9. 第 2 個 task 執行 f()
  10. f() 內的 process.nextTick(() => console.log(1));console.log(1) 放入 nextTickQueue
  11. f() 內的 Promise.resolve().then(() => console.log(2));console.log(2) 放入 micro task queue
  12. 結束後,因為步驟 11 所以 micro task queue 又有新的 task,因此執行 console.log(2) 印出 2,結束後 micro task queue 沒有 task
  13. 這時會再回來檢查 nextTickQueue,因為步驟 10 所以有新的 task,執行 console.log(1) 印出 1,結束後 nextTickQueue 沒有 task
  14. event queue 會來回在 nextTickQueuemicro task queue 內的 task 清空後檢查另一邊,直到 2 邊的 task 都完全清空後進到下個階段,所以下面程式會無窮來回執行 nextTickQueuemicro task queue 內的 task:
const f = (g) => process.nextTick(() => {console.log('nextTick'); g(f)}); const g = (f) => Promise.resolve().then(() => {console.log('promise'); f(g)}); f(g); g(f);

timer
pending
idle, prepare
poll
check
closed