我在微任务队列 nextTick 队列中的 nodeJs 中看到很多地方比 promise 队列具有更高的优先级但是当我在我的设备中尝试它的示例时我没有得到预期的输出。但是在在线节点编译器上我得到了预期的输出。
process.nextTick(()=>console.log('In nextTick')) Promise.resolve().then(()=>console.log('In Promise'))
不同之处在于,在您的设备上,您将脚本解释为 ES 模块 (ESM),而 Web REPL 必须设置为 CommonJS (CJS)。
在 ESM 中,您的脚本在全局
async
上下文中运行,所以 我猜(我仍然需要检查源...) 事件循环处于微任务阶段。从微任务阶段排队微任务将防止事件循环离开微任务队列,因此您的回调将立即执行。
您可以通过以 ESM 身份运行此脚本来看到这一点:
const t1 = Date.now();
const fn = () => Promise.resolve().then(() => {
if(Date.now()-t1 < 5000) {
Promise.resolve().then(fn);
}
else {
console.log("all promises done");
}
});
process.nextTick(() => console.log("tick"));
fn();
这将阻止脚本 5 秒,然后打印“所有承诺完成”,然后是“滴答”。
“报价阶段”也是如此(不确定确切的命名法):
const t1 = Date.now();
const fn = () => process.nextTick(() => {
if(Date.now()-t1 < 5000) {
process.nextTick(fn);
}
else {
console.log("all ticks done");
}
});
Promise.resolve().then(() => console.log("promise"));
fn();
此脚本将锁定 5 秒,然后打印“all ticks done”,然后是“promise”。
注意即使在浏览器中微任务也以同样的方式阻塞.
所以我们不能真的说一个优先级比另一个高,但是可以说,从“timeout phase”或“network phase”开始,会先进入“tick phase”。所以像
这样的脚本setImmediate(() => {
process.nextTick(()=>console.log('In nextTick'))
Promise.resolve().then(()=>console.log('In Promise'))
});
将打印“In nextTick”然后“In Promise”,无论主脚本被解释为 ESM 还是 CJS。