原文章地址:http://mp.weixin.qq.com/s/FZefHsoVqtkcjUJK3KwRFw
文章中主要讲了Node的四个定时器(setTimeout(),setInterval(),setImmediate(),process.nextTick())以及代码运行的规则。
- 同步比异步代码更早执行
- 异步代码中本轮循环比次轮循环更在执行,其中Node规定process.nextTick()和Promise的回调函数追加再本轮循环,而setTimeout()、setInterval()、setImmediate()是追加再次轮循环中的
- process.nextTick()是异步事件中最快执行的
- Promise的回调函数追加在process.nextTick()事件的微任务中,也被划为本轮循环
- 事件循环的初始化过程
同步任务
发出异步请求
规划定时器生效的时间
-
执行 process.nextTick()等等
- 事件循环的六个阶段
timers 定时器阶段,若当前事件满足定时器条件,则执行定时器的回调函数,反之离开
I/O callbacks 执行除定时器和关闭请求的其他所有回调函数
idle, prepare libuv内部调用,libuv是Node规定的库用来负责异步事件在主线程上的执行时间
poll 等待未返回的I/O事件,此阶段消耗事件较长
check 执行定时器的回调函数
-
close callbacks 执行用来关闭请求的回调函数,如 socket.on('close', ...)
- 另外需要注意的是setTimeout的第二个参数默认为 0。但是实际上,Node 做不到0毫秒,最少也需要1毫秒,根据官方文档,第二个参数的取值范围在1毫秒到2147483647毫秒之间。即setTimeout(fn,0)等同于setTimeout(fn,1)。
setTimeout(()=>console.log(1)); setImmediate(()=>console.log(2));
理论上说上面两行代码的执行顺序应该是先打印1再打印2,但在实际操作中却是有可能先打印2再打印1的,取决于当时的系统状况,若进入事件循环到了1ms,就先打印1再打印2,若没有1ms,则回跳过setTimeout去执行setImmediate的回调。