2

首先,我们来看一下event loop是干嘛用的。

比如,现在执行了一个2s的setTimeout,浏览器主线程执行,然后调用web API中的setTimeout,接下来浏览器的定时器线程开始计数,2s之后,事件触发线程开始处理setTimeout的回调函数,把这个回调函数扔到任务队列中,此时,event loop开始执行任务队列。所以,event loop可以理解成是来执行任务队列的。

在开始介绍event loop之前,还需要了解两个概念,就是宏任务和微任务。

宏任务和微任务是异步任务的两种分类:
宏任务包括script,setTimeout/setInterval,setImmediate,I/O和UI rendering;
而微任务包括了Promise,Object.observe,Mutation.Observer和postMessage。

知道它是干嘛用的,又知道了宏任务和微任务,那么我们来看看它到底是个啥。

Event loop,按照字面意思翻译就是 事件循环。事件,就是处理异步任务,处理宏任务和微任务,而循环就是循环去处理。那么它是怎么样处理的呢?

现在js的执行环境主要有两个,一个是浏览器,一个是nodejs,这两个环境中都有对应的event loop。下面我们分开来说。

浏览器的Event loop

来看张图
浏览器EventLoop处理模型

  1. 首先执行的是script任务,script任务是全局任务,属于宏任务
  2. 宏任务执行完毕,开始执行所有的微任务
  3. 微任务执行完毕,再取任务队列中的一个宏任务执行

可能只看这些还是不清晰,那么我们再来一个例子。

console.log(1);
setTimeout(function() {
    console.log(2);
}, 0);
Promise.resolve().then(function() {
    console.log(3)
});
console.log(4);

你觉得这段代码会怎么输出?

输出结果:
1
4
3
2

为什么呢?

  1. 首先执行script全局任务,会输出1,4
  2. script执行完,开始判断微任务是否为空。现在显然有一个微任务Promise,那么开始执行Promise,输出3
  3. 执行完了Promise,微任务清空,微任务队列就为空了,然后重新渲染,再次判断任务队列中是否有任务
  4. 此时任务队列中有setTimeout宏任务,开始执行,于是最后输出2

这就是一个完整的过程。

一个Event loop有一个或多个任务队列,每一个Event loop只有一个微任务队列

以上就是浏览器的Event loop

nodejs的Event loop

nodejs的event loop有6个阶段:

  1. timers: 执行timers的回调
  2. pending callbacks:系统操作的回调
  3. idle,pepare:内部使用
  4. poll:等待新I/O事件
  5. check:执行setImmediate回调
  6. close callbacks:内部使用

以上这些阶段,每一个阶段都有一个callback的先进先出的队列需要执行,当event loop运行到指定阶段时,该阶段的fifo队列将会被执行,当队列callback执行完成或执行的callback数量超过该阶段的上限时,event loop会转入下一个阶段。

这6个阶段,我们现在只关注3个,分别是timer,poll和check。

再来看个图

Untitled Diagram (1).png

proccess.nextTick() 是一个异步的node API,但是不属于event loop阶段,调用时,event loop会停下来,先去执行这个方法的回调


叁木同学
14 声望0 粉丝

不定期分享工作中的大大小小的坑