深刻解析Node.js Event Loop各階段

今天小編就爲你們分享一篇關於Node.js Event Loop各階段講解,寫的十分的全面細緻,具備必定的參考價值,對此有須要的朋友能夠參考學習下。若有不足之處,歡迎批評指正。前端

Event Loop階段描述圖node

timersgit

timer階段處理setTimeout於setInterval回調,開始處理的時機與poll階段有關聯。github

pending callbacksbash

該階段執行某些系統操做的回調,好比TCP套接字在鏈接時收到ECONNREFUSED。異步

網上有一些將該階段稱爲I/O callbacks的文章都是過期錯誤的,具體能夠移步Node.js官方庫下面的這個issue: #1118socket

idle, prepareoop

內部使用,忽略。學習

poll優化

poll是一個核心階段,等新I/O事件的觸發,以及執行I/O相關回調。Node.js中出現異步的絕大部分狀況都是I/O操做,它們的回調基本都在這個階段被執行。

poll階段主要作兩件事:

  • 計算須要爲新的的I/O事件等待多久

當進入poll階段,若是隊列爲空且不存在setImmediate與就緒的timer,Node.js會在這裏block必定的時間等待新的I/O事件到來,而後當即執行其回調。這種狀況具體block等待多久是不具體的,但若是在block必定時間後仍沒有新到達的I/O事件,能夠確定循環依舊會進入check階段或者回到timer階段。

  • 處理該階段隊列中的事件

當進入poll階段,若是隊列不爲空且沒有就緒的timer,Node.js會在這裏執行隊列中的callback直到隊列爲空或者執行的callback數達到系統設定的某個值。隨後Node.js檢查是否存在預設的setImmediate,存在話就進入check階段,不然開始檢查timer就緒狀況選擇回到timer階段或者進入check階段。

對於poll階段,經過閱讀官方的文檔有些細節也沒弄清楚,用僞代碼表示出來:

enter pool phase:
if (has timer scheduled) {
  // 官方沒有提到這種狀況會作什麼
}
else {
  if (isEmpty(queue)) {
    if (has(setImmediate)) {
      // 進入check階段
    }
    else if (!isEmpty(timer)) {
      // 回到timer階段
    }
    else {
      // 等待新的I/O事件
      // 新的I/O事件觸發回調當即執行,執行完成以後的邏輯不清楚
    }
    // 目前看來只有存在setImmediate時纔會進入check階段,這確定不合理
  }//在此我向你們推薦一個前端全棧開發交流圈:619586920 突破技術瓶頸,提高思惟能力
  if (!isEmpty(queue)) {
    let result = execute(queue);
    if (result === 'queue is empty') {
      // 官方沒講後續邏輯
      // 猜想是回到隊列爲空的處理邏輯中
    }
    if (result === 'reached hard limit') {
      // 官方沒有解釋這裏的後續邏輯
      // 也許與queue is empty同樣對待
    }
  }
}//在此我向你們推薦一個前端全棧開發交流圈:619586920 突破技術瓶頸,提高思惟能力
複製代碼

疑惑重點是從poll階段出來的時機以及去向不是很是明確,但以我目前的水平和精力只能到此爲止。

check

當poll階段執行完成會進入到check階段執行,該階段的執行內容是全部setImmediate回調。

close callbacks

socket的異常關閉,'close'事件的回調會在該階段執行。

process.nextTick

process.nextTick常常被用來作異步調用,但它並不屬於事件循環的內容,process.nextTick中的回調被放在nextTickQueue中等待「當前操做」完成後被當即處理,與事件循環中的階段沒有聯繫,當前操做的原文定義是:「An operation is defined as a transition from the underlying C/C++ handler, and handling the JavaScript that needs to be executed.」,指的是在一段Javascript代碼執行完切換到C/C++層時會處理nextTickQueue。

在此我向你們推薦一個前端全棧開發交流圈:619586920 突破技術瓶頸,提高思惟能力

文章提到了一個特例是Deduplication,這是Node.js內部一個優化特性,當在timer和check階段,同時有多個須要執行的回調時,切換隻會發生一次,因此nextTick回調執行在這種狀況下看似有所延後。 代碼示例:

setImmediate(() => {
  console.log('1');
  process.nextTick(() => console.log('2'));
});
setImmediate(() => {
  console.log('3');
  process.nextTick(() => console.log('4'));
});
複製代碼

存在兩個setImmediate,進入check階段後須要在執行全部setImmediate的回調代碼後纔會產生切換,從而執行nextTick回調,所以上面代碼的運行結果是:「1 3 2 4」,除上述場景外,nextTick都會先於setImmediate執行。

總結

由於Node.js的Event Loop我看了有那麼二、3回,但常常忘,因此此次記錄下來,作個備忘。因爲太多知識容易忘記,又發現寫文章的一個優勢:「幫助記憶便於複習」。

結語

感謝您的觀看,若有不足之處,歡迎批評指正。

相關文章
相關標籤/搜索