Open LuckyWinty opened 4 years ago
setImmediate()约等于setTimeout(()=>{}, 0) , 都是异步执行,不同的setTimeout在timer阶段执行,而setImmediate是在nodejs的check阶段执行。如果setTimeout设置成0,那么他们的执行顺序是、有可能前有可能后是不确定的。这是因为setTimeout设置为0也需要1ms才能执行(浏览器是4ms),而event loop的启动从timer, i/o,到poll 时间有可能多大于1ms,如果大于1ms,这时 timeout是1ms,已经符合执行条件settimeout会立即执行,然后接着执行check阶段的setImmediate。如果event loop启动后到了poll阶段,耗时小于1ms,比如用了 0.8ms,那么这是 settimeout是1ms,不符合条件跳到check阶段先执行setImmediate然后再执行setTimeout。如果这两个事件调用是在某个i/0类的函数中,那么他们的执行顺序就是固定的,不会出现在前后执行的不确定性。
setImmediate() 和 setTimeout() 很类似,但是基于被调用的时机,他们也有不同表现。
执行计时器的顺序将根据调用它们的上下文而异。如果二者都从主模块内调用,则计时器将受进程性能的约束。举个例子,有如下代码:
上面代码应该先输出1,再输出2,但是实际执行的时候,结果却是不确定,有时还会先输出2,再输出1。
这是因为setTimeout的第二个参数默认为0。但是实际上,Node 做不到0毫秒,最少也需要1毫秒,根据官方文档,第二个参数的取值范围在1毫秒到2147483647毫秒之间。也就是说,setTimeout(f, 0)等同于setTimeout(f, 1)。
实际执行的时候,进入事件循环以后,有可能到了1毫秒,也可能还没到1毫秒,取决于系统当时的状况。如果没到1毫秒,那么 timers 阶段就会跳过,进入 check 阶段,先执行setImmediate的回调函数。
但是,如果是这样的情况,输出顺序就固定了,例:
在上述代码中,一定是先输出2,再输出1。因为两个代码写在 IO 回调中,IO 回调是在 poll 阶段执行,当回调执行完毕后队列为空,发现存在 setImmediate 回调,所以就直接跳转到 check 阶段去执行回调了,执行完成后再去到 timers 阶段,然后执行setTimeout。