- 首先,
node当中的event loop和浏览器中的是不相同的 nodejs的event loop是基于libuv,而浏览器的event loop则在html5的规范中明确定义- libuv真正地实现了nodejs的event loop(有源码),而html5只是提供了event loop的模型,留给各大浏览器去自己实现源码
Node当中的Event loop分为6个阶段,每一个阶段都有自己的队列,他们会按照顺序反复运行
- timers阶段
- 1.检查timer队列中是否有到期的timer回调,如果有,按照timerID升序执行
- 2.检查timer队列中是否有
process.nextTick任务,如果有,全部执行 - 3.检查timer队列中是否有
microtask,如果有,全部执行 - 4.退出该阶段
- 执行过程:查看 到期的Timer回调 => process.nextTick => microTask
- 注意:一个
timer指定的时间并不是准确时间,而是在到达这个时间后尽快执行回调,可能会因为系统正在执行别的事物而延迟
- I/O callback阶段
- 1.检查是否有处于
pending的I/O回调,如果有,执行回调;如果没有,则直接退出该阶段 - 2.检查process.nextTick任务,如果有,就全部执行
- 3.检查microTask任务,如果有,全部执行
- 4.退出该阶段
- 注意:I/O阶段会执行除了
close、setInterval、setTimeout、setImmediate的所有回调 - 注意:上一轮循环中会有少数的I/O callback被延迟到这一轮循环中的这一阶段执行
- 1.检查是否有处于
- idle,prepare:可省略,仅内部使用
- poll阶段(轮询阶段)
- 1.首先检查是否存在尚未完成的回调(类似于网络请求是否已经拿到数据),如果存在尚未完成的回调,则分两种情况执行:
- 第一种情况:
- 1.1如果有可用回调(到期的定时器和一些I/O事件等),则执行所有可用回调
- 1.2检查process.nextTick任务,有就全部执行
- 1.3检查microTask,有就全部执行
- 1.4退出该阶段
- 第二种情况
- 1.1如果没有可用回调
- 1.2检查是否有immediate回调,如果有,退出poll阶段(去check执行);如果没有,阻塞在此阶段,一直等到有新的事件通知为止
- 第一种情况:
- 如果不存在尚未完成的回调
- 直接退出poll阶段
- 1.首先检查是否存在尚未完成的回调(类似于网络请求是否已经拿到数据),如果存在尚未完成的回调,则分两种情况执行:
- check阶段
- 1.如果有
setImmediate的回调,则立即全部执行 - 2.检查是否有process.nextTick任务,如果有则全部执行
- 3.检查是否有microTask任务,如果有则全部执行
- 4.退出该阶段
- 1.如果有
- close callbacks阶段
- 1.执行
close事件的callback - 2.检查process.nextTick任务,有则全部执行
- 3.检查microTask任务,有则全部执行
- 4.退出closing阶段
- 1.执行
- 最后:检查是否有活跃的handles(定时器、I/O等事件)
- 如果有,继续进入下一轮循环
- 如果没有,则结束事件循环,退出程序
-
Node循环中产生的执行队列:
Timers Queue,I/O Queue,Check Queue,Close Queue -
循环过程:按照六个阶段进行循环,每次拿出当前阶段的队列中的所有任务然后全部执行,清空NextTick Queue,然后清空Microtask Queue,再执行下一阶段。全部六个阶段执行完毕之后,进入下轮循环,即:
- 清空当前循环内的
Timers Queue,清空NextTick Queue,清空Microtask queue - 清空当前循环的
I/O Queue,清空NextTick Queue,清空Microtask queue - 清空当前循环的
Check Queue,清空NextTick Queue,清空Microtask queue - 清空当前循环的
Close Queue,清空NextTick Queue,清空Microtask queue
- 清空当前循环内的
-
注意:
-
如果在timers阶段执行时创建了
setImmediate,则会在check阶段执行;如果在timers阶段创建了setTimeout,由于timers已取出完毕,则会进入下轮循环 -
setTimeout优先级比setImmediate高
-
每个阶段系统都会从当前阶段的
callback queue中取出任务并执行,当队列为空或者被需要执行的callback数量达到上限时,就会进入下一个阶段
-
上述为本人在学习中的一些见解,如有错误烦请各位指正,感谢!
该文所有内容源自网络并结合了自己的理解,如有侵权请务必告知。