4 / 8 node中的 setTimeout 和 setImmediate 有什麼區別

前面的話

前端日問,鞏固基礎,不打烊!!!

解答

首先兩者都是定時器,在node中有4種定時器:

  • setTimeout
  • setInterval
  • setImmediate
  • process.nextTick

在node中,I/O處理方面有自己的libuv引擎,libuv引擎中事件循環分爲6個階段:
在這裏插入圖片描述

  • timers階段: 執行timer(setTimeout 、setInterval)的回調
  • poll階段: 獲取新的I/O事件,適當的條件下node將阻塞在這裏。
  • check階段: 執行setImmediate()的回調。
    setTimeout是在timer階段,而setImmediate是在check階段。

ps:

在poll階段主要執行兩件事:執行I/O回調、處理隊列中的事件。

當事件循環在poll階段時:
1、如果poll隊列不爲空,則執行隊列中的回調;
2、 如果隊列中爲空,且有setImmediate回調要執行,就會立即停止poll階段,進入check階段執行setImmediate的回調;
3、 如果隊列爲空,並且沒有setImmediate回調要執行,poll階段將等待新的callback被加入。
4、如果有timer的話並且poll隊列爲空,則會檢查是否有timer超時,如果有的話就回到timer階段,執行相應的回調。

setTimeout與setImmediate區別
  • 如果二者都從主模塊內調用,則計時器將受進程性能的約束。舉個例子,有如下代碼:

    setTimeout(() => console.log(1));
    setImmediate(() => console.log(2));
    

    如果二者都從主模塊內調用,則計時器將受進程性能的約束。 輸出結果不一定,有可能先是1,也有可能先是2。

    因爲setTimeout的第二個參數默認爲0,但實際上,Node做不到0秒,最少也要1毫秒。那麼進入事件循環後,如果沒到1毫秒,那麼timers階段就會跳過,進入check階段。

  • 如果兩者在I/O週期內調用,始終先執行setImmediate回調。

    const fs = require('fs');
    
    fs.readFile(__filename, () => {
      setTimeout(() => {
        console.log('timeout');
      }, 0);
      setImmediate(() => {
        console.log('immediate');
      });
    });
    

因爲I/O回調是在poll階段執行,當回調執行完畢之後隊列爲空,發現存在setImmediate的回調就會進入check階段,執行完畢後,再進入timer階段。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章