事件循环
Node 中的事件循环机制
plaintext
┌───────────────────────────┐
┌─>│ timers │
│ └─────────────┬─────────────┘
│ ┌─────────────┴─────────────┐
│ │ pending callbacks │
│ └─────────────┬─────────────┘
│ ┌─────────────┴─────────────┐
│ │ idle, prepare │
│ └─────────────┬─────────────┘ ┌───────────────┐
│ ┌─────────────┴─────────────┐ │ incoming: │
│ │ poll │<─────┤ connections, │
│ └─────────────┬─────────────┘ │ data, etc. │
│ ┌─────────────┴─────────────┐ └───────────────┘
│ │ check │
│ └─────────────┬─────────────┘
│ ┌─────────────┴─────────────┐
└──┤ close callbacks │
└───────────────────────────┘
1️⃣ timers
定时器
定时器阶段 setTimeout
setInterval
- 开始计时
- 执行定时器的回调 (定时器的回调只能在这里执行)
2️⃣ pending
callbacks
系统阶段 (不关心)
3️⃣ idle
prepare
准备阶段 (不关心)
4️⃣ poll
轮询
轮询阶段,核心阶段
- 如果回调队列里有待执行的回调函数 (非定时器回调,而是其它异步操作的回调)
- 从回调队列中取出回调函数,同步执行 (按顺序执行),直到回调队列为空了,或者达到系统最大限度。
- 如果回调队列为空
- 如果有设置过
setImmediate
- 进入下一个check阶段,目的:为了执行
setImmediate
所设置的回调
- 进入下一个check阶段,目的:为了执行
- 如果未设置过
setImmediate
- 在此阶段停留,等待回调函数被插入回调队列
- 若定时器到点了,进入下一个
check
阶段,原因:为了走第五阶段,随后走第六阶段,随后第一阶段 (最终目的)
- 如果有设置过
5️⃣ check
专门用于执行 setImmediate
所设置的回调阶段
6️⃣ close
callbacks
关闭回调阶段
process.nextTick()
用于设置立即执行函数 (能在任意阶段优先执行)
js
// 延迟定时器
setTimeout(() => {
console.log(1)
})
// 立即执行函数(回调)
setImmediate(() => {
console.log(2);
});
// 立即执行函数(回调)
process.nextTick(() => {
console.log(3);
});
console.log(4);
// 输出:4 3 1 2