弑君者

V1

2022/12/24阅读:34主题:默认主题

彻底解释清楚Event loop

为什么需要event loop

如果一个事情,出现没有解决任何问题,那么它存在就没有任何意义。

因为js的main thread,一个时间只能处理一件事情,所以才需要event loop。

当然现在浏览器也可以使用web workers,开一个线程,执行其他一些任务;

什么是event loop

很多人都听过event loop,那么标准中是如何定义的呢?

event loop规范地址

To coordinate events, user interaction, scripts, rendering, networking, and so forth, user agents must use event loops as described in this section. Each agent has an associated event loop, which is unique to that agent.

可以看到标准里边介绍了,就是为了协调事件、用户交互、脚本、UI 渲染、网络请求,所以才必须使用 eventloop 来协调。

一个event loop 有一个或者多个task queues,但是要注意task queues是set而不是queue

An event loop has one or more task queues. A task queue is a set of tasks.

事件、ajax请求、解析html、回调等都是task

  1. Events

Dispatching an Event object at a particular EventTarget object is often done by a dedicated task.

Not all events are dispatched using the task queue; many are dispatched during other tasks.

  1. Parsing

The HTML parser tokenizing one or more bytes, and then processing any resulting tokens, is typically a task.

  1. Callbacks Calling a callback is often done by a dedicated task.

  2. Using a resource When an algorithm fetches a resource, if the fetching occurs in a non-blocking fashion then the processing of the resource once some or all of the resource is available is performed by a task.

  3. Reacting to DOM manipulation Some elements have tasks that trigger in response to DOM manipulation, e.g. when that element is inserted into the document.

当遇到task的时候,会按照一定的原则放入到task queue里边;

如果遇到microtask ,会加入到microtask queue里边,event loop有一个microtask queue

这里要注意的是microtask有可能是会被放入到task queue里边的

It is possible for a microtask to be moved to a regular task queue, if, during its initial execution, it spins the event loop. This is the only case in which the source, document, and script evaluation environment settings object set of the microtask are consulted; they are ignored by the perform a microtask checkpoint algorithm

浏览器的event loop整体架构

这里Web APIs 是js内部控制

可以通过一段代码,查看是如何运行的

console.log('Hi');
setTimeout(function cb1(
    console.log('cb1');
}, 5000);
console.log('Bye');
代码执行过程
代码执行过程

可以看到当遇到setTimeout的时候,首先会在Web APIs里边等待时间到期才放入到task queue中等待执行。

规范event loop的执行机制

  1. 首先从task queue 里边取出一个task 执行

这里需要注意的是microtask不会在这一步执行,但是有特殊情况,也会选择 microtask

Remember that the microtask queue is not a task queue, so it will not be chosen in this step. However, a task queue to which the microtask task source is associated might be chosen in this step. In that case, the task chosen in the next step was originally a microtask, but it got moved as part of spinning the event loop.

  1. 执行微任务
  1. Perform a microtask checkpoint.
  1. ui render

这里需要注意的是浏览器可能不一定会render,比如规范里边这两种情况

the user agent believes that updating the rendering of the Document's node navigable would have no visible effect, and the Document's map of animation frame callbacks is empty.

  1. 后面会依次检查resize、scroll等事件
  1. For each fully active Document in docs, flush autofocus candidates for that Document if its node navigable is a top-level traversable.
  1. For each fully active Document in docs, run the resize steps for that Document. [CSSOMVIEW]
  1. For each fully active Document in docs, run the scroll steps for that Document. [CSSOMVIEW]
  1. For each fully active Document in docs, evaluate media queries and report changes for that Document. [CSSOMVIEW]
  1. For each fully active Document in docs, update animations and send events for that Document, passing in now as the timestamp. [WEBANIMATIONS]
  1. For each fully active Document in docs, run the fullscreen steps for that Document. [FULLSCREEN]
  1. 执行requestAnimationframe的回调 可以看到在13步才会执行animation frame callbacks
  1. For each fully active Document in docs, run the animation frame callbacks for that Document, passing in now as the timestamp.
  1. 当执行完rfa以后,就会重新计算样式,看看有没有resize

可以看到规范里边说的是重新计算styles

Recalculate styles and update layout for doc

  1. requestIdleCallback的执行

当满足一下几种情况的时候,如果还有时间,就会执行requestIdleCallback

this is a window event loop there is no task in this event loop's task queues whose document is fully active this event loop's microtask queue is empty hasARenderingOpportunity is false

其它还有很多特殊情况要处理,就不一一说了。

node.js event loop

  1. timer

setTimeoue和setInterval 会放入这个阶段,但是什么时候执行,需要在poll阶段确定

执行时间也是不固定,比如设置了100ms,可能得等到105ms才执行

setTimeout(() => {
  const delay = Date.now() - timeoutScheduled;

  console.log(`${delay}ms have passed since I was scheduled`);
}, 100);
  1. pending callbacks 这个阶段执行一些tcp错误等

  2. poll

如果此时队列不空,就执行,如果为空,就看下有没有setImmediate,有就执行,没有就等待callbacks加入

When the event loop enters the poll phase and there are no timers scheduled, one of two things will happen:

If the poll queue is not empty, the event loop will iterate through its queue of callbacks executing them synchronously until either the queue has been exhausted, or the system-dependent hard limit is reached.

If the poll queue is empty, one of two more things will happen:

If scripts have been scheduled by setImmediate(), the event loop will end the poll phase and continue to the check phase to execute those scheduled scripts.

If scripts have not been scheduled by setImmediate(), the event loop will wait for callbacks to be added to the queue, then execute them immediately.

Once the poll queue is empty the event loop will check for timers whose time thresholds have been reached. If one or more timers are ready, the event loop will wrap back to the timers phase to execute those timers' callbacks.

  1. check 执行setImmediate

  2. close callbacks

执行一些socket close 事件

视频讲解

event loop 基础讲解

event loop 基础讲解

分类:

前端

标签:

JavaScript

作者介绍

弑君者
V1