这两者有什么区别,我什么时候才能使用另一个?
如果使用 CommonJS 模块,使用 setImmediate 调用 setTimeout 会出现不可预测的行为。但如果切换到ESM(package.json中的“type”:“module”),它总是会在setTimeout之前执行setImmediate。
setTimeout(() => {
console.log('timeout');
}, 0);
setImmediate(() => {
console.log('immediate');
});
Run Code Online (Sandbox Code Playgroud)
为什么会出现这种情况?这与 ESM 模块异步加载有关吗?
我对 Node.js 文档的以下段落感到困惑。
setImmediate()与setTimeout()...定时器的执行顺序将根据调用它们的上下文而变化。如果两者都是从主模块内部调用的,那么计时将受到进程性能的约束(这可能会受到计算机上运行的其他应用程序的影响)。
例如,如果我们运行以下不在 I/O 周期(即主模块)内的脚本,则两个计时器的执行顺序是不确定的,因为它受到进程性能的约束:
接下来显示以下示例
// timeout_vs_immediate.js
setTimeout(() => {
console.log('timeout');
}, 0);
setImmediate(() => {
console.log('immediate');
});
Run Code Online (Sandbox Code Playgroud)
$ node timeout_vs_immediate.js
timeout
immediate
$ node timeout_vs_immediate.js
immediate
timeout
Run Code Online (Sandbox Code Playgroud)
我不明白是什么导致结果不确定。由于该timers阶段发生在该check阶段之前,因此安排的回调不应该setTimeout总是在安排的回调之前执行吗setImmediate?我认为事件循环中的阶段顺序不会因为上下文切换或其他原因而改变。
该文件还指出
但是,如果在一个 I/O 周期内移动这两个调用,则始终先执行立即回调:
好的,但是所谓的“I/O 周期”与主模块有何不同?
我知道有很多相关的问题,但所有答案都只是通过引用文档来陈述这一事实,而没有解释非确定性在哪里发挥作用,所以我认为这不是重复的。