Event Loop - msforest/notebook GitHub Wiki

大家都知道 js 是单进程单线程模式,既减少了多线程上下文切换的开销,又降低了复杂场景的难度。但是 js 并不因为单线程,性能有所下降;相反,js 使用事件循环实现类似并发的操作,我们把它叫做“异步”

预习概念

  • 异步 vs 并发
  • 微任务 vs 宏任务

Node.js 的事件循环

根据官网事件循环得出如下图: event loop

Callback Queue 事件循环的每个阶段内部都含有一个 callback 队列,当运行到某个阶段时,按照 FIFO 的顺序依次执行 callback,直到队列为空才进入下一个阶段。

Microtasks 俗称“微任务”,会在主线程和事件循环的每一个阶段执行之后进入该“微任务”队列。 “微任务”包含:

  1. process.nextTick();
  2. promise.then()

也会形成一个 FIFO 队列。nextTick 优先于 promise.then

Timer 不支持传入字符串参数

  1. setTimeout
  2. setInterval
    ps: 根据mdn显示,setTimeout/setInterval 使用同一个 ID 池

Pending

Idel,prepare

Poll 处理和 I/O 相关的 callback;如 fs 模块。若 poll 队列不为空,则执行;若为空,1. setImmediate 不为空,则进入下一阶段;2. setImmediate 为空,则等待队列被添加执行

Check

  1. setImmediate 若 poll 阶段为空而 check 队列不为空时,会执行 check 队列,而不是在 poll 阶段瞎等待

Close

浏览器的事件循环

browser event loop

macrotask(tasks)

包含执行整体的 js 代码,事件回调,XHR 回调,定时器(setTimeout/setInterval/setImmediate),IO 操作,UI render

microtask

更新应用程序状态的任务,包括 promise 回调,MutationObserver,process.nextTick,Object.observe 每个 macrotask 任务队列执行完之后都会执行 microtask 队列 ps: macrotask/microtask 类似于 callback 队列

js call stack

负责主线程的任务调度,函数回调会形成一个栈帧,帧中包含当前执行函数的参数和局部变量等上下文信息,执行完后弹出当前栈帧进行垃圾回收。call stack 是 LIFO。

参考: