Node.js 事件循环机制:Promise、nextTick、setTimeout 与 setImmediate 执行顺序详解
本文深入解析 Node.js 事件循环机制,详细阐述同步代码、process.nextTick、Promise.then、setTimeout 及 setImmediate 的执行优先级。通过具体代码示例,展示宏任务与微任务的调度顺序,帮助开发者准确掌握异步回调的执行逻辑。
本文旨在深入解析 Node.js 中 Promise.then、process.nextTick、setTimeout 以及 setImmediate 的执行顺序,并提供具体的代码示例供参考。
典型代码执行顺序示例
首先,通过一个典型的代码片段来引出问题:
setImmediate(function(){
console.log(1);
},0);
setTimeout(function(){
console.log(2);
},0);
new Promise(function(resolve){
console.log(3);
resolve();
console.log(4);
}).then(function(){
console.log(5);
});
console.log(6);
process.nextTick(function(){
console.log(7);
});
console.log(8);
这段代码执行后的输出顺序是什么?
正确的输出结果如下:
3 4 6 8 7 5 2 1
宏任务与微任务概念解析
在分析输出结果之前,我们需要明确 Node.js 事件循环中的几个核心概念:
宏任务(macro-task)包括:脚本整体代码、setTimeout、setInterval、setImmediate、I/O 操作以及 UI 渲染。
微任务(micro-task)包括:process.nextTick、原生 Promise、Object.observe 以及 MutationObserver。
事件循环执行步骤详解
第一步,执行脚本整体代码,具体执行流程如下:
- 注册一个宏任务:setImmediate。
- 注册一个宏任务:setTimeout。
- 注册一个微任务:Promise.then 的回调函数,并继续执行同步代码 console.log(3); resolve(); console.log(4);。此时控制台输出 3 和 4。尽管 resolve() 已被调用,但由于当前同步代码尚未执行完毕,Promise.then 的回调不会立即执行。
- 执行 console.log(6),控制台输出 6。
- 注册一个微任务:process.nextTick。
- 执行 console.log(8),控制台输出 8。
- 经过上述同步代码的执行阶段,控制台已依次输出 3、4、6、8。
第二步,由于微任务的优先级高于宏任务,系统开始处理微任务队列。
当前微任务队列中包含两个任务,根据优先级规则,process.nextTick 的优先级高于 Promise.then。
因此,先执行 process.nextTick 回调,输出 7;随后执行 Promise.then 回调,输出 5。
第三步,当微任务队列执行完毕后,开始执行宏任务。由于 setTimeout 的优先级高于 setImmediate,因此先执行 setTimeout 回调,输出 2;最后执行 setImmediate 回调,输出 1。
整个过程看似同步执行,但实际上是基于 Event Loop(事件循环)机制进行的异步调度。
新版 Node.js 中的特殊行为
关于微任务与宏任务的执行顺序,可以参考《深入浅出 Node.js》中的一个经典示例:
//加入两个nextTick的回调函数
process.nextTick(function () {
console.log('nextTick延迟执行1');
});
process.nextTick(function () {
console.log('nextTick延迟执行2');
});
// 加入两个setImmediate()的回调函数
setImmediate(function () {
console.log('setImmediate延迟执行1');
// 进入下次循环
process.nextTick(function () {
console.log('强势插入');
});
});
setImmediate(function () {
console.log('setImmediate延迟执行2');
});
console.log('正常执行');
运行该代码,得到的结果如下:
正常执行 nextTick延迟执行1 nextTick延迟执行2 setImmediate延迟执行1 setImmediate延迟执行2 强势插入
在新版 Node.js 中,process.nextTick 执行完毕后,会遍历并执行所有 setImmediate 回调,直到 setImmediate 队列清空后才跳出当前循环。因此,在两个 setImmediate 执行完毕后,队列中仅剩第一个 setImmediate 内部注册的 process.nextTick,最终输出“强势插入”。
观察者优先级机制
关于优先级的另一个清晰版本如下:
观察者优先级机制。
在每次事件循环检查中,各阶段观察者的优先级分别为:
idle 观察者 > I/O 观察者 > check 观察者。
idle 观察者对应:process.nextTick。
I/O 观察者对应:常规 I/O 回调,如网络、文件、数据库 I/O 等。
check 观察者对应:setTimeout 和 setImmediate,其中 setTimeout 优先级高于 setImmediate。
执行优先级总结
总结。
- 同步代码的执行优先级高于异步代码;
- new Promise(fn) 中的 fn 函数是同步执行的;
- 优先级顺序为:process.nextTick > Promise.then > setTimeout > setImmediate。
以上就是本文的全部内容,希望这些解析能对您的学习有所帮助,欢迎继续支持本站。
怎么在本地运行JavaScript脚本:Node.js下载安装与环境配置教程
2026-11-05 09:02:33
JavaScript开发环境怎么搭建:Node.js安装与VS Code配置指南
2026-11-03 23:36:59
JavaScript零基础入门:环境搭建与第一个Hello World
2026-11-03 23:34:09
NW.js 是什么:基于 Chromium 和 Node.js 的桌面应用框架
2026-11-03 15:14:00
nvm、n 和官方安装包:哪种 Node.js 升级方式更适合你
2026-11-03 14:54:28
