Node JS 並非 「Single thread environment」
- 而是會有
一個
thread來負責處理主程式
以及Event loop
- 主程式
- 也就是循序執行我們所打的每一行 JS code
- 先處理完主程式, 才會處理 event loop 收到的 callback
1 | setTimeout(function() { |
result :
1 | 5s later |
Event loop
- 跑完一次 loop 稱作一個
tick
- 每個 Phase 有自己個 queue, 用來存放 callback function
- 到該 Phase 時, queue 中的 callback 會依序執行
- 當無等待的
timer
或I/O 事件
時, Event loop 結束 Phases in loop:
- timer
- 執行
setTimeout()
,setInterval()
的 callback
- 執行
- I/O callback
- 執行一些 I/O 完成後的 callback
- e.g.
- 從網路擷取資料
- 寫檔案/讀檔案
- 當 I/O 操作發生錯誤時
- e.g.
- 執行一些 I/O 完成後的 callback
- idle, prepare
- 執行一些 libuv 內部的事情
- poll
- 輪詢特定 I/O
- e.g. http listening
- 當 Event loop 中其他 Phase 中所有 queue 中皆空, 且有
一個以上的輪詢 I/O
時, 會 block 在此 phase- e.g. http.listen(…)
- 假設有其他 Phase 之非同步事件完成, 有 callback 加入了該 Phase 的 queue, 則會跳至該 Phase 去執行
- 輪詢特定 I/O
- check
- 執行
setImmidiate()
之 callback
- 執行
- close
- 執行 close 相關之 callback
- e.g. file.close()
- 執行 close 相關之 callback
- timer
process.nextTick
andmicrotasks
- 其 callback queue 會立即加入
當前Phase
的 queue 的末端- 在主程式結束後也包含了這個 queue
- 包含了:
- process.nextTick() 的 callback
- microtasks:
Promise
的 reslove/reject
- nextTick queue 會在 microtasks queue 前執行
- 其 callback queue 會立即加入
setImmidiate() v.s. process.nextTick()
- process.nextTick()
- 會將 task queue 在當前 Phase 的後面
- 當
遞迴
Call 時, 將導致遲遲無法進去下一個 Phase
, 塞住整個 event loop
- setImmidiate()
- 會將 task queue 在 check phase
- 當遞迴 Call 時, 會將 task queue 在
下一次
iteration loop 的 check phase- 遞迴呼叫時,
不會 block 住 event loop
.
- 遞迴呼叫時,
- process.nextTick()
參考文獻
- 非同步程式碼之霧:Node.js 的事件迴圈與 EventEmitter
- Udemy course - Advanced Nodejs concept
- Github issue - 浏览器和NodeJS中不同的Event Loop #234
- 深入理解js事件循环机制(Node.js篇)