浏览器中的EventLoop是根据HTML5定义的规范来实现的,不同的浏览器可能会有不同的实现,而Node中是由libuv实现的。
给出一个Node的架构图:
会发现libuv中主要维护了一个EventLoop和workerthreads(线程池);
EventLoop负责调用系统的一些其他操作:文件的IO、Network、child-processes等;
libuv是一个多平台的专注于异步IO的库,它最初是为Node开发的,但是现在也被使用到Luvit、Julia、pyuv等其他地方。

Node事件循环的阶段
事件循环像是一个桥梁,是连接着应用程序的JavaScript和系统调用之间的通道:
无论是我们的文件IO、数据库、网络IO、定时器、子进程,在完成对应的操作后,都会将对应的结果和回调函数放到事件循环(任务队列)中;
事件循环会不断的从任务队列中取出对应的事件(回调函数)来执行;
但是一次完整的事件循环Tick分成很多个阶段:
- 定时器(Timers):本阶段执行已经被 setTimeout()和 setInterval() 的调度回调函数。
- 待定回调(Pending Callback):对某些系统操作(如TCP错误类型)执行回调,比如TCP连接时接收到ECONNREFUSED。
- idle,prepare:仅系统内部使用。
- 轮询(Poll):检索新的 I/O 事件;执行与 I/O 相关的回调。
- 检测(check):setImmediate0 回调函数在这里执行。
- 关闭的回调函数:一些关闭的回调函数,如:socket.on(‘close’,…)。
Node事件循环的阶段图解

Node的宏任务和微任务
从一次事件循环的Tick来说,Node的事件循环更复杂,它也分为微任务和宏任务:
宏任务(macrotask):setTimeout、setinterval、I0事件、setmmediate、close事件;
微任务(microtask):Promise的then回调、process.nextTick、queueMicrotask;
但是,Node中的事件循环不只是 微任务队列和 宏任务队列:
微任务队列:
next tick queue :process.nextTick ;
other queue :Promise的then回调、queueMicrotask ;
宏任务队列:
timer queue :setTimeout, setInterval ;
poll queue:IO事件;
check queue :setmmediate ;
check queue:close事件;
Node事件循环的顺序
所以,在每一次事件循环的tick中,会按照如下顺序来执行代码:
- next tick microtask queue ;
- other microtask queue ;
- Dtimer queue ;
- poll queue ;
- check queue ;
- close queue ;

876

被折叠的 条评论
为什么被折叠?



