轮训优先级
- 过期计时器和间隔队列(timer阶段) - 使用 setTimeout 添加的过期计时器的回调或者使用 setInterval 添加的间隔函数。
- IO 事件队列(IO poll)
如果有任何未决的任务需要处理,事件循环就不会阻塞。如果这里没有未决的任务需要执行,它将会阻塞直到下一个 timer 到期,会重新激活循环,激活循环也是冲setImmediate开始然后转移到timer阶段。
- 完成的 I/O 事件立即的队列(Immediate queue) - 使用 setImmediate 函数添加的回调
- 关闭操作队列(Close Handlers Queue) 任何一个 close 事件处理器。
以上每个阶段完成后都会去微任务队列里面查找是否有微任务,如果有的话就去执行它。
微任务
- 下一个运转队列(Next Ticks Queue) 使用 process.nextTick() 函数添加的回调
下一个运转队列比微队列有着更高的优先级。尽管它们都在事件循环的两个阶段之间处理,在一个阶段的结尾 libuv 回到 Node 的跟高层进行通信。这意味着在开始处理 promise 的微队列之前,下一个运转队列是空的。
下一个运转队列的优先级比 promise 的高仅仅适合于 V8 提供的原生 JS 提供的 promise。如果你使用一个 q 库或者 bluebird, 你将会观察到一个不同的结果,因为它们提早于原生的 promise,有不同的语义。 q 和 bluebird 处理 promise 也有不同的方式,后面的文章我会解释。
- 其他的微队列(other Microtasks Queue) - 包含其他的微队列如成功的 Promise 回调
考虑下面的代码
Promise.resolve().then(() => console.log('promise1 resolved'));
Promise.resolve().then(() => console.log('promise2 resolved'));
Promise.resolve().then(() => {
console.log('promise3 resolved');
process.nextTick(() => console.log('next tick inside promise resolve handler'));
});
Promise.