为何添加console.log后Node.js中setTimeout与setImmediate执行顺序固定?
为什么添加
console.log('hey')后setTimeout与setImmediate的执行顺序固定了? 要弄明白这个问题,得先搞清楚Node.js事件循环里两个关键阶段的逻辑:
- Timers阶段:负责处理
setTimeout、setInterval这类定时器回调。注意,哪怕你给setTimeout传0延迟,Node.js里实际的最小执行延迟是1ms——也就是说回调最早要等1ms后才能被执行。 - Check阶段:专门处理
setImmediate的回调,这个阶段在Timers阶段之后的几个阶段才会触发。
代码片段1顺序波动的原因
代码片段1的同步代码只有注册定时器的操作,执行速度极快,耗时远小于1ms。当同步代码跑完进入事件循环时:
- 如果此时还没到1ms的节点,Timers阶段找不到可以执行的
setTimeout回调,就会跳过这个阶段,直接往后走,直到Check阶段执行setImmediate的回调;等下一轮事件循环回到Timers阶段,才会执行setTimeout。 - 如果刚好在同步代码执行完时,系统时间刚好过了1ms(比如系统调度的微小波动),Timers阶段就会先执行
setTimeout的回调,再到Check阶段执行setImmediate。
这两种情况随机出现,就导致了输出顺序不固定。
代码片段2顺序固定的原因
添加的console.log('hey')虽然只是一行输出,但它会增加同步代码的执行耗时——哪怕只是几微秒,加上之前注册定时器的操作,总耗时就会超过1ms。当同步代码执行完进入事件循环时,setTimeout的1ms延迟已经满足,Timers阶段会优先执行所有setTimeout的回调,之后事件循环走到Check阶段,再执行setImmediate的回调,所以顺序就固定成了hey(同步)→setTimeout1→setTimeout2→setImmediate1→setImmediate2。
内容的提问来源于stack exchange,提问作者RedPotato
相关产品推荐
相关产品推荐

