一、Node事件循环
我们把每一圈的事件循环叫做「一次循环」、又叫「一次轮询」、又叫「一次Tick」。
一次循环要经过六个阶段:
- timers:计时器(setTimeout、setInterval等的回调函数存放在里边),本阶段执行setTimeout()和setInterval()的调度回调函数
- pending callback:待定回调,执行延迟到下一个循环迭代的I/O回调
- idle prepare:仅系统内部使用
- poll:轮询队列(除timers、check之外的回调存放在这里)检索新的I/O事件;执行与I/O相关的回调,其余情况node将在适当的时候在此阻塞
- check:检查阶段(使用 setImmediate 的回调会直接进入这个队列),也就是说setImmediate()回调函数在这里执行
- close callbacks:关闭的回调函数,一些关闭的回调函数,如:socket.on('close',...)。
工作原理
1.每一个阶段都会维护一个事件队列。可以把每一个圈想象成一个事件队列。
2.这就和浏览器不一样了,浏览器最多两个队列(宏队列、微队列)。但是在node里边有六个队列
3.到达一个队列后,检查队列内是否有任务(也就是看下是否有回调函数)需要执行。如果有,就依次执行,直到全部执行完毕、清空队列。
4.如果没有任务,进入下一个队列去检查。直到所有队列检查一遍,算一个轮询。
其中,timers
、pending callback
、idle prepare
等执行完毕后,到达poll
队列。
那么nextTick和promise如何参与事件循环呢?
- 二者都是「微队列」,执行异步微任务。(事件循环中的都是宏任务)
- 二者不是事件循环的一部分,程序也不会开启额外的线程去处理相关任务。(理解:promise里发网络请求,那是网络请求开的网络线程,跟Promise这个微任务没关系)
- 微队列设立的目的就是让一些任务「马上」、「立即」优先执行。
- nextTick与Promise比较,nextTick的级别更高。
事件循环中,每执行一个回调前,先按序清空一次nextTick和promise。