iT邦幫忙

2021 iThome 鐵人賽

DAY 14
2
Software Development

全端工程師生存筆記系列 第 14

[面試][後端]請簡述 Node.js 的 Event Loop

熟悉的起手式:「我方便問你一個 Node.js 核心的問題嗎?」

這是一個在了解後,無論面試還是工作,CP 值都很高的題目,建議讀者要真的融會貫通。

大綱

  1. 請簡述 Node.js 的 Event Loop

    • 1.1 面試官為什麼會問?
    • 1.2 面試官想從答案確認什麼?
    • 1.3 筆者提供的簡答
  2. 回答問題所需具備的知識

    • 2.1 Event Loop 執行的邏輯
    • 2.2 用 Node.js 範例程式確認自己是否理解 Event Loop
    • 2.3 解析 Node.js 範例程式執行順序
  3. 衍伸問題

    • 3.1 可以簡述 Node.js 跟 JavaScript 的差異嗎?
    • 3.2 readFile 和 createReadStream 函式的差異?
    • 3.3 REPL 是什麼?

1. 請簡述 Node.js 的 Event Loop

1.1 面試官為什麼會問?

只要你的履歷上有 Node.js,10 間公司至少有 3 間會問這個常見面試題;而且問題的起手式出奇的一致:「我方便問你一個 Node.js 核心的問題嗎?」


1.2 面試官想從答案確認什麼?

  • 你了解 Event Loop 對 Node.js 的重要性
  • 你能大概說明 Event Loop 每個階段的任務
  • 如果出白板題要你解釋程式執行的順序,你可以正確回答

1.3 筆者提供的簡答

Node.js 之所以高效,是因為採取單執行緒與 Event Loop 的概念;將所有需要等待結果、請求外部資源的函式,全部丟到 Event Loop 中等待;而 Event Loop 的邏輯是 Node.js 底層用 C 語言撰寫的 libuv 庫來運行的。


2. 回答問題所需具備的知識

2.1 Event Loop 執行的邏輯

https://ithelp.ithome.com.tw/upload/images/20210919/20103256BPTVtHaRmr.png

  • 了解 MacroTask 的 6 個階段
    • Timer
      等計時器(setTimeout、setInterval)的時間一到,會把他們的 callback 放在這裡等待執行。
    • Pending callbacks
      作業系統層級使用(ex:TCP errors、sockets 連線被拒絕)。
    • Idle, Prepare
      內部使用。
    • Polling:
      • 如果 Queue 不為空,依次取出 callback 函數執行,直到 Queue 為空或是抵達系統最大限制。
      • 如果 Queue 為空但有設置「setImmediate」就進入 Check 階段。
      • 如果 Queue 為空但沒有設置「setImmediate」就會在 Polling 階段等待,直到 Queue 有東西或是 Timer 時間抵達。
    • Check
      處理 setImmediate 的 callback。
    • Close callbacks
      處理關閉連線、檔案的 callback。

Macrotask Queue 在 Evevnt Loop 優先層級較低,接下來介紹優先層級更高的兩個 Queue。

  • NextTick Queue 優先層級最高
    「process.nextTick()」的 callback 可以隨意插隊;只要這個 Queue 有東西就會優先執行。
  • MicroTask Queue 優先層級次高
    「Promise」的狀態從 pending 轉變為 resolve 或 reject 時,執行的 callback 會進入這個 Queue。

    注意Promise 在創建時是同步的,不會進入 Event Loop。


2.2 用 Node.js 範例程式確認自己是否理解 Event Loop

大家可以先用紙筆模擬看看下面程式的執行順序:

console.log("start");

process.nextTick(function () {
  console.log("nextTick1");
});

setTimeout(function () {
  console.log("setTimeout");
}, 0);

new Promise(function (resolve, reject) {
  console.log("promise");
  resolve("resolve");
}).then(function (result) {
  console.log(result);
});

(async function () {
  console.log("async");
})();

setImmediate(function () {
  console.log("setImmediate");
});

process.nextTick(function () {
  console.log("nextTick2");
});

console.log("end");

如果答案跟下面結果一樣,那代表你很了解 Node.js 的 Event Loop 邏輯:

start
promise
async
end
nextTick1
nextTick2
resolve
setTimeout
setImmediate

2.3 解析 Node.js 範例程式執行順序

  • SETP 1: 順序執行,先把同步函式解決。

    1. 因為 Promise 在創建時是同步的,所以會先執行。

    2. 在 function 前面加上 async 宣告為異步函式,執行時會被轉換為 Promise。

      console.log("start");
      
      new Promise(function (resolve, reject) {
        console.log("promise");
        resolve("resolve");
      }).then(function (result) {
        console.log(result);
      });
      
      (async function () {
        console.log("async");
      })();
      
      console.log("end");
      
  • STEP 2: 進入 Event Loop。

    1. 如果執行過程中遇到 NextTick Queue 就優先執行。

      process.nextTick(function () {
        console.log("nextTick1");
      });
      
      process.nextTick(function () {
        console.log("nextTick2");
      });
      
    2. 在處理完最高優先層級後,如果執行過程中遇到 MicroTask Queue 就執行。

      new Promise(function (resolve, reject) {
        console.log("promise");
        resolve("resolve");
      }).then(function (result) {
        console.log(result);
      });
      
    3. 在前兩個高優先層級的 Queue 清空後,返回 Event Loop 繼續執行,setTimeout 設定的時間已到先執行。

      setTimeout(function () {
        console.log("setTimeout");
      }, 0);
      
    4. 接著再在「Check」 階段執行 setImmediate

      setImmediate(function () {
        console.log("setImmediate");
      });
      

以上步驟執行完成後就是範例程式的解答啦~希望對大家理解 Event Loop 有幫助。


3. 衍伸問題

3.1 可以簡述 Node.js 跟 JavaScript 的差異嗎?

考點:確認求職者是否理解自己天天使用的工具

JavaScript 是程式語言,可以在合適的瀏覽器中運行;而 Node.js 是一個能執行JavaScript 的環境,它以 Chrome V8 引擎為核心,再加上 C/C++套件,讓 Sever 端也可以執行 JavaScript。


3.2 readFile 和 createReadStream 函式的差異?

考點:判斷求職者過去專案中使否使用過這類函式,並理解差異

readFile 函式會將讀取到的完整內容存在記憶體後傳給使用者,而 createReadStream 函式則是逐塊讀取檔案,不是全部存在記憶體中;因此要讀取較大的檔案時,建議使用 createReadStream ,利用其逐塊讀取的特性能減少使用者等待時間。


3.3 REPL 是什麼?

考點:對專有名詞是否熟悉,能否解釋

REPL(Read Eval Print Loop)是一個用來執行程式語言的虛擬環境

就像是我們在瀏覽器的 Console 可以執行 JavaScript 程式碼;在安裝完 Node.js 後,新增一個 JavaScript 檔,在終端機輸入node xxx.js便可以執行它。


感謝大家的閱讀,如果喜歡我的文章可以訂閱接收通知;如果有幫助到你,按Like可以讓我更有寫文的動力,我們明天見~

參考資源:

  1. Node.js 的 Event Loop (事件輪詢)到底在做什麼?(筆者部落格)
  2. 15 個常見的 Node.js 面試問題及答案
  3. 你有沒有想過,到底 Server 是如何「同時處理多個 requests」的? - Node.js 篇

上一篇
[面試][後端]你會的後端框架不只一個,可以說明一下它們之間的差異嗎?
下一篇
[面試][後端]在正式 API 完成前,如何讓要串接的工程師不要空等?
系列文
全端工程師生存筆記30

1 則留言

1
screenleon
iT邦新手 1 級 ‧ 2021-09-29 16:57:49

感謝分享
讓我對nodejs有更深一層的認識了

很高興文章有幫助到你/images/emoticon/emoticon42.gif

我要留言

立即登入留言