Node.js 的事件循环是其异步编程模型的核心。它允许 Node.js 处理大量的并发操作,而不会阻塞线程。以下是对 Node.js 事件循环的详细说明:
事件循环的执行顺序
特殊的回调队列
-
process.nextTick:process.nextTick回调会在当前操作完成后立即执行,而不等待进入下一个事件循环阶段。- 它优先于其他所有的回调。
-
微任务队列(Microtask Queue):
- 包括
Promise的回调和process.nextTick。 - 在每个阶段结束后,事件循环会检查微任务队列,并执行所有的微任务。
- 包括
事件循环的阶段
-
定时器阶段(Timers):
- 处理
setTimeout和setInterval的回调。 - 这些回调会在指定的时间到达后尽快执行。
- 处理
-
待定回调阶段(Pending Callbacks):
- 处理一些系统操作的回调,例如 TCP 错误类型的回调。
- 这些回调通常是由操作系统触发的。
-
闲置、准备阶段(Idle, Prepare):
- 仅供内部使用。
- Node.js 在这里执行一些内部操作。
-
轮询阶段(Poll):
- 检索新的 I/O 事件;执行与 I/O 相关的回调(几乎所有的回调都在这个阶段执行),除非有定时器设置。
- 如果没有定时器设置,事件循环会在这个阶段停留,等待新的 I/O 事件。
-
检查阶段(Check):
- 执行
setImmediate回调。 setImmediate回调会在轮询阶段之后立即执行。
- 执行
-
关闭回调阶段(Close Callbacks):
- 执行一些关闭的回调,如
socket.on('close', ...)。
- 执行一些关闭的回调,如
示例
以下是事件循环的执行顺序示例:
console.log('Start');
setTimeout(() => {
console.log('Timeout callback');
}, 0);
setImmediate(() => {
console.log('Immediate callback');
});
process.nextTick(() => {
console.log('Next Tick callback');
});
Promise.resolve().then(() => {
console.log('Promise callback');
});
console.log('End');
- 同步代码:
console.log('Start')和console.log('End')立即执行。 process.nextTick:process.nextTick回调在当前操作完成后立即执行。- 微任务队列:
Promise回调在当前操作完成后立即执行,但在process.nextTick之后。 setImmediate:setImmediate回调在检查阶段执行。setTimeout:setTimeout回调在定时器阶段执行。
实际输出:
Start
End
Next Tick callback
Promise callback
Immediate callback
Timeout callback