1.settimeout和setimmediate的执行顺序取决于事件循环阶段。在主模块代码中,settimeout(fn, 0)通常先执行,因为事件循环从timers阶段开始,随后进入check阶段执行setimmediate;但在i/o回调中,setimmediate几乎总是优先,因为事件循环在poll阶段结束后会直接进入check阶段处理setimmediate回调,再回到timers阶段处理settimeout。2.此外,process.nexttick和promise微任务具有更高的优先级,会在当前阶段结束前执行,优先于settimeout和setimmediate。

提到Node.js的事件循环,
setTimeout
setImmediate
setTimeout(fn, 0)
setImmediate
setImmediate
setTimeout(0)

要真正理解
setTimeout
setImmediate
setTimeout
setInterval
setImmediate
check
setImmediate
close
socket.on('close')当我们调用
setTimeout(fn, 0)
setImmediate(fn)

那么,关键点来了:
在主模块代码(非I/O回调)中:事件循环启动,会首先进入timers阶段。如果
setTimeout(0)
setImmediate
setTimeout

setTimeout(() => {
console.log('setTimeout executed');
}, 0);
setImmediate(() => {
console.log('setImmediate executed');
});
// 运行结果:通常是 'setTimeout executed' 然后 'setImmediate executed'
// 但偶尔也会因为系统负载等原因,setTimeout的最小延迟导致其在下一个tick才被处理,
// 使得setImmediate反而先执行。所以这里用“通常”而非“总是”。在I/O回调中:这是个特别的场景。当一个I/O操作完成(比如文件读取完毕),它的回调会在
poll
poll
check
timers
setTimeout(0)
setImmediate()
setImmediate
check
setTimeout(0)
timers
const fs = require('fs');
fs.readFile(__filename, () => {
setTimeout(() => {
console.log('setTimeout in I/O callback');
}, 0);
setImmediate(() => {
console.log('setImmediate in I/O callback');
});
});
console.log('Script started, waiting for I/O...');
// 运行结果:
// Script started, waiting for I/O...
// setImmediate in I/O callback
// setTimeout in I/O callback这两种场景的差异,就是理解它们执行顺序的关键。
这几乎是Node.js新手必踩的坑,我第一次遇到时也疑惑了好一阵子。说白了,这和事件循环的启动流程有关。当Node.js脚本开始运行,事件循环的第一个“行程”总是从
timers
setTimeout(0)
setImmediate()
setTimeout
timers
setImmediate
check
事件循环在第一次迭代时,会先处理
timers
setTimeout(0)
pending callbacks
poll
check
setImmediate
当然了,这里有一个小细节:
setTimeout(fn, 0)
setTimeout
timers
setImmediate
setTimeout(0)
setImmediate
这个现象,在我看来,是Node.js事件循环设计中非常精妙的一点,它保证了I/O相关操作的即时性。设想一下,当一个文件读取完成,或者一个网络请求的数据包抵达,这些I/O事件的回调会在
poll
timers
poll
check
setImmediate
这是因为
setImmediate
poll
setTimeout(0)
所以,当I/O回调执行完毕,事件循环会“顺理成章”地进入
check
setImmediate
check
timers
setTimeout(0)
Node.js的异步世界远不止
setTimeout
setImmediate
process.nextTick()
timers
poll
check
process.nextTick()
setImmediate(() => console.log('setImmediate'));
setTimeout(() => console.log('setTimeout'), 0);
process.nextTick(() => console.log('process.nextTick'));
Promise.resolve().then(() => console.log('Promise.then'));
// 运行结果:
// process.nextTick
// Promise.then
// setTimeout (或 setImmediate,取决于具体运行环境和主线程任务)
// setImmediate (或 setTimeout)在我看来,
process.nextTick
Promise微任务:包括
Promise.resolve().then()
async/await
process.nextTick
其他宏任务:
setInterval
setTimeout
timers
net.createServer().on('connection')http.Server().on('request')poll
setImmediate
check
socket.on('close')close callbacks
理解这些不同任务队列的优先级,以及它们在事件循环不同阶段的执行位置,是掌握Node.js异步编程的关键。它能帮助我们预测代码行为,并编写出更健壮、更高效的异步应用。这就像在排队,有些队伍有特权通道,有些则需要按部就班,而微任务就是那些能插队的“VIP”。
以上就是setTimeout和setImmediate在事件循环中的执行顺序是怎样的?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号