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阶段。

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