node.js事件循环是分六阶段严格顺序执行的异步调度机制,每阶段清空对应回调队列后插入微任务;process.nexttick属最高优先级微任务,setimmediate属check阶段宏任务。

Node.js 的事件循环不是“一边轮询一边执行”的简单循环,而是一个有严格阶段顺序、分层调度的异步任务协调机制。它的核心目标是在单线程下高效处理 I/O 密集型操作,同时兼顾回调执行的可预测性。
六个阶段按固定顺序依次执行
每次事件循环迭代(tick)都严格遵循以下六阶段顺序,每个阶段处理对应队列中的回调,且**一个阶段内的所有回调会全部执行完,才进入下一阶段**:
-
Timers:执行已到期的
setTimeout和setInterval回调;注意:即使设为0,也必须等系统时钟判定“已到期”才触发,不保证立即执行。 -
Pending Callbacks:执行某些底层系统操作的延迟回调,比如 TCP 连接被拒绝(
ECONNREFUSED)后的错误处理,开发者通常无需主动干预。 - Idle / Prepare:仅 Node.js 内部使用,用于轮询前的准备,对外不可见,可忽略。
-
Poll:最关键的 I/O 阶段——检索并执行文件读写、网络请求(如
fs.readFile、http.request)等完成后的回调;若无待处理 I/O 回调,该阶段可能阻塞等待(除非有setImmediate或定时器待触发)。 -
Check:专门执行
setImmediate注册的回调,总在 Poll 阶段之后、Close 前运行。 -
Close Callbacks:执行资源关闭类回调,例如
socket.on('close', ...)或stream.destroy()后的清理逻辑。
微任务总在阶段切换间隙插入
微任务(microtask)不归属上述六个阶段,而是在每个宏任务阶段执行完毕后、进入下一阶段前统一清空:
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
- 包括
process.nextTick()(优先级最高)、Promise.then/catch/finally、MutationObserver(浏览器)等; - 关键规则:每轮阶段执行后,只要微任务队列非空,就持续执行直到清空,期间不进入下一阶段;
- 例如:Poll 阶段执行完一个 I/O 回调 → 立即执行所有 pending 的
nextTick和Promise回调 → 才进入 Check 阶段。
process.nextTick 与 setImmediate 的本质区别
两者常被误认为等价,实则调度时机完全不同:
-
process.nextTick是当前操作结束后立即执行,属于微任务,甚至早于本轮 Promise 回调; -
setImmediate是本轮 Poll 阶段结束后执行,属于宏任务,排在 Check 阶段,比setTimeout(fn, 0)更晚(后者在 Timers 阶段); - 典型输出顺序(同步代码 → nextTick → Promise → setTimeout → setImmediate)印证了微任务优先于所有宏任务阶段。
实际执行流程示意
一次完整事件循环的调度链路如下:
- 同步代码执行完毕(调用栈清空)→
- 执行所有
process.nextTick回调 → - 执行所有 Promise 微任务 →
- 进入 Timers 阶段(执行到期定时器)→
- 执行微任务(再次清空)→
- 进入 Pending → Idle → Poll → Check → Close,每个阶段后均检查并执行微任务 →
- 若 Poll 阶段无 I/O 回调且无定时器待触发,可能等待新事件,再继续下一轮。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










