本文是我之前关于 Node.js 事件循环的系列文章的简短跟进。在之前的系列文章中,我详细讨论了Timers,setImmediate,process.nextTick,Promises等等。

但是,自 Node.js v11.0.0 起,对 setTimeout,setImmediate,process.nextTick 和Promises 的行为进行了一些重大更改。在本文中,我将讨论这些新的更改以及 Node < v11.0.0 和 Node ≥ v11.0.0 之间的功能的一些比较。如果您错过了我之前关于 Node.js事件循环的任何文章,我建议您从以下链接中阅读它们然后返回此处以查看 Node v11.0.0中引入的新更改。

详解

如果您分别在浏览器和 Node.js 中单独运行以下代码,会得到完全相反的结果。

setTimeout(() => console.log('timeout1'));
setTimeout(() => {
    console.log('timeout2')
    Promise.resolve().then(() => console.log('promise resolve'))
});
setTimeout(() => console.log('timeout3'));
setTimeout(() => console.log('timeout4'));

在浏览器中,会输出如下结果:

timeout1
timeout2
promise resolve
timeout3
timeout4

然而在低于v11.0.0版本的 Node.js 中,会输出以下结果:

timeout1
timeout2
timeout3
timeout4
promise resolve

在 Node.js 的实现中,当程序横跨 C ++ / JavaScript 边界时,会在事件循环( event loop )的每个阶段之间执行 process.nextTick 回调和微任务 ( microtasks, 例如,promise回调 )。因此,在执行 Promise 的回调之前,所有定时器的回调都会在事件循环( event loop )的定时器阶段执行,从而产生上述输出。

然而,浏览器和Node之间的这种矛盾的输出已经被讨论了很长一段时间了,并且一个特性(或bug修复)已经登陆 Node.js v11.0.0 用以跟踪浏览器行为。使用此功能,Node.js v11.0.0或更高版本将输出与浏览器输出匹配的以下内容: