![](https://i-blog.csdnimg.cn/blog_migrate/20e682c87357b158096e12e2e3ba244d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/ff2c18820f0eda9521146f776fb900bd.jpeg)
* 定时器(timer): 在这个阶段执行 setTimeout、setInterval的回调函数
* 待定回调(pending callbacks):某些系统操作(如 TCP 错误类型)执行回调
* idle, prepare:仅系统内部使用。
* 轮询(poll):检索新的 I/O 事件; 执行与 I/O 相关的回调(几乎所有情况下,除了关闭的回调函数,那些由计时器和 setImmediate() 调度的之外)
* 检测(check):setImmediate() 回调函数在这里执行。
* 关闭的回调函数(close callbacks):一些关闭的回调函数,如:socket.on('close', ...)。
![](https://i-blog.csdnimg.cn/blog_migrate/a125aa59947d2a2d6b9eacb4ea0e594c.png)
微任务:promise的then函数的回调、queueMicrotask、process.nextTick
宏任务: setTimeout、setInterval、io事件、setImmediate、close事件
执行顺序也和javascript中一致,先执行主线程的任务,然后接着执微任务,微任务执行完成再执行宏任务,具体的执行顺序如下。
微任务队列
next tick queue:process.nextTick
other tick queue:promise的then函数、queueMicrotask
宏任务队列
timer queue: setTimeout、setInterval
poll queue: io事件
check queue: setImmediate
close queue: close事件
async function async1() {
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2')
}
console.log('script start')
setTimeout(function () {
console.log('setTimeout0')
}, 0)
setTimeout(function () {
console.log('setTimeout2')
}, 300)
setImmediate(() => console.log('setImmediate'));
process.nextTick(() => console.log('nextTick1'));
async1();
process.nextTick(() => console.log('nextTick2'));
new Promise(function (resolve) {
console.log('promise1')
resolve();
console.log('promise2')
}).then(function () {
console.log('promise3')
})
console.log('script end')
首先声明了 async1 和 async2函数,只有调用才会被放入调用栈中,所以此时不会执行,往下执行输出 "script start"。
继续向下执行,将 "setTimeout0" 放入 宏任务的 timer queue 中,继续执行,"setTimeout2" 需要延迟300ms执行,不放入 timer queue中,接着把 "setImmediate" 放入 check queue 中,把 "nextTick1" 放入 next tick queue 中。
此时执行函数 async1,输出 "async1 start",在函数 async1 中执行 async2,输出 "async2",把 "async1 end" 放入 other queue当中,此时函数 async1执行完成,继续向下执行,将"nextTick2"放入next tick queue中,排在"nextTick1"后面,继续输出 "promise1",将"promise3"放在other queue中,排在"async1 end"后面,输出"promise2",最后输出"script end",此时主线程的内容都执行完成。
来到微任务队列,微任务队列中先执行 next tick queue 中的内容,依次输出 "nectTick1"、"nectTick2",再执行 other queue 中的内容,依次输出"async1 end"、"promise3"。
最后执行宏任务队列中的任务,先执行 timer queue,输出 "setTimeout0",这里没有io事件(poll),往下执行check quue,输出 setImmediate,没有关闭回调函数阶段( close callbasks),一次事件循环结束,来到第二次、第三次事件循环,此时300ms后,"setTimeout2" 被加入到宏任务队列中的 timer queue,事件循环中没有其他的队列,直接输出 "setTimeout2",事件循环结束。
简单图示如下
![](https://i-blog.csdnimg.cn/blog_migrate/632d8486f41023e83a401bd25fe7a8ea.png)
setTimeout(() => {
console.log("setTimeout");
}, 0);
setImmediate(() => {
console.log("setImmediate");
});
按照宏任务队列中各任务的执行顺序,setTimeout属于timer queue,setImmediate属于check queue,按理说会先输出setTimeout,但实际情况会是什么样的呢,我们看一下以下输出情况
![](https://i-blog.csdnimg.cn/blog_migrate/c6af658a886009690cf14a69309fbbcc.png)