宏任务队列和微任务队列执行顺序规则
- 事件循环基本概念:Node.js 的事件循环是一个持续运行的循环,它不断检查调用栈是否为空,并按顺序处理不同队列中的任务。
- 宏任务队列:常见的宏任务包括
setTimeout
、setInterval
、setImmediate
、I/O
操作等回调。每次事件循环,事件循环引擎会从宏任务队列中取出一个宏任务放入调用栈执行,当调用栈清空后,才会去处理微任务队列。
- 微任务队列:常见的微任务有
Promise.then
、process.nextTick
(Node.js 特有的,它的优先级比其他微任务更高)。在一个宏任务执行完,调用栈清空后,事件循环会立即处理微任务队列,将微任务队列中的所有任务依次放入调用栈执行,直到微任务队列为空,然后再进入下一轮事件循环,从宏任务队列中取出下一个宏任务。
代码示例及执行流程说明
console.log('start');
setTimeout(() => {
console.log('setTimeout');
}, 0);
Promise.resolve()
.then(() => {
console.log('Promise.then 1');
})
.then(() => {
console.log('Promise.then 2');
});
process.nextTick(() => {
console.log('process.nextTick');
});
console.log('end');
- 初始阶段:代码开始执行,首先输出
start
,然后遇到 setTimeout
,将其回调函数放入宏任务队列。
- Promise 微任务处理:接着遇到
Promise.resolve().then
,将 .then
回调函数放入微任务队列。process.nextTick
也将其回调放入微任务队列,但 process.nextTick
优先级更高。
- 主线程结束:输出
end
,此时主线程代码执行完毕,调用栈清空。
- 微任务执行:事件循环开始处理微任务队列,由于
process.nextTick
优先级高,先输出 process.nextTick
,然后依次执行 Promise.then
回调,输出 Promise.then 1
和 Promise.then 2
。
- 宏任务执行:微任务队列清空后,进入下一轮事件循环,从宏任务队列中取出
setTimeout
的回调函数放入调用栈执行,输出 setTimeout
。至此,整个代码执行完毕。