在開始討論 Node.js 的 event loop 之前,我們需要先了解 JavaScript 是單線程的語言。這意味著任何時候,JavaScript 引擎只能執行一個任務。然而,網頁應用程式通常需要處理許多不同的任務,例如響應使用者互動、從伺服器獲取資料或更新視窗中的內容。為了管理這些多樣化的任務,JavaScript 使用了一個事件循環來監聽事件並以特定的順序執行它們。
Node.js 是一個基於 Chrome V8 引擎的開源運行環境,用於建立後端服務和命令列工具。與瀏覽器中的情況類似,Node.js 也有一個內置的事件循環,用於管理非同步 I/O 操作和其他背景工作。
當一個 Node.js 應用程式啟動時,它會創建一個執行緒並初始化它的核心模組,如 timers、I/O、idle、prepare 和 check 等。接下來,event loop 會開始運作,等待事件的發生。這些事件可能是 setTimeout()、setInterval()、http 請求或其他可能被 JavaScript 代碼觸發的非同步操作。
以下是 Node.js 中 event loop 的主要階段及其描述:
1. timers – 在這個階段中,所有由 `setTimeout()` 和 `setInterval()` 定義的延遲函數都會被安排執行。
2. pending callbacks – 此階段處理那些仍在等待 I/O 完成的通知的所有剩餘的掛起 callback。這包括了許多的 Ajax 請求。
3. idle, prepare – 如果存在,這兩個階段是由操作系統定義的空檔時間進行的優先級較低的工作。在大多數情況下,我們可以忽略這些階段。
4. poll (又稱為 check) – 在這個階段,event loop 等待新的 I/O 請求或者新定的 timer 到期。在 poll 模式下,如果沒有更多的 I/O 活動,event loop 會進入休眠狀態直到有新的活動產生。
5. handle events in the queue – 如果前四個階段中有任何一個添加了新的待處理事項到事件隊列中(通常是下一輪迭代要執行的 function),那麼事件循環就會處理該隊列中的第一個事件。
6. close callbacks – 最後,如果所有的其他 stage 都已經清空並且所有的非同步 I/O 已完成,event loop 將檢查是否有任何 stream 或 socket 需要清理。如果有,則執行 close callbacks。
一旦事件循環完成了所有的階段,它會再次從頭開始循環,重複整個過程。這種設計允許 Node.js 高效地處理大量的輸入和輸出請求,同時保持其單線程模型的簡潔性。
需要注意的是,在某些特殊情況下,比如高負載的情況下,event loop 可能會變得非常忙碌而無法及時處理一些關鍵任務,例如回應 HTTP 請求。這可能會導致應用程式性能下降甚至崩潰。因此,在開發高性能的 Node.js 應用程式時,理解和管理 event loop 是非常重要的。