CommonJS 与 ESM 中 setImmediate() 和 setTimeout() 回调的优先级

问题描述 投票:0回答:1

如果使用 CommonJS 模块,使用 setImmediate 调用 setTimeout 会产生不可预测的行为。但如果你切换到ESM(package.json中的“type”:“module”),它总是会在setTimeout之前执行setImmediate。

setTimeout(() => {
  console.log('timeout');
}, 0);

setImmediate(() => {
  console.log('immediate');
});

为什么会出现这种情况?这与ESM中模块是异步加载的事实有关吗?

javascript node.js es6-modules commonjs event-loop
1个回答
-1
投票

在 CommonJS 环境中,例如 Node.js,当以非常短的延迟(例如 0 毫秒)快速连续调用时,

setTimeout
setImmediate
之间的执行顺序可能无法预测。这是由于 Node.js 处理 CommonJS 模块及其同步加载的方式所致。

使用 ESM(ECMAScript 模块)和

"type": "module"
中设置的
package.json
选项,模块将异步加载并遵循更标准化的事件处理模型。在这种情况下,因为模块是异步加载的,所以
setImmediate
更有可能在
setTimeout
之前执行,即使延迟为 0 毫秒。

确保所需执行顺序的一种可能的解决方案是使用不依赖于模块加载顺序的代码结构。例如,您可以使用延迟稍大于 0 毫秒的

setImmediate
setTimeout
来确保所需的顺序:

setImmediate(() => {
  console.log('immediate');
});

setTimeout(() => {
  console.log('timeout');
}, 1); // Use a slightly larger delay than 0

这样,无论模块加载行为如何,您都可以确保

setImmediate
setTimeout
之前执行。

© www.soinside.com 2019 - 2024. All rights reserved.