await-async-事件循环(二)

275 阅读2分钟

跟着coderwhy学习

1.Node的事件循环

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

image.png

2.Node事件循环的阶段

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

3.Node事件循环的阶段图解

image.png

4.Node的宏任务和微任务

  • 我们会发现从一次事件循环的Tick来说,Node的事件循环更复杂,它也分为微任务和宏任务:
    • 宏任务(macrotask):setTimeout、setInterval、IO事件、setImmediate、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:setImmediate;
      • close queue:close事件;

5.Node事件循环的顺序

  • 所以,在每一次事件循环的tick中,会按照如下顺序来执行代码:
    • next tick microtask queue;
    • other microtask queue;
    • timer queue;
    • poll queue;
    • check queue;
    • close queue;

6.Node执行面试题

image.png