My Personal Blog

Published on

浏览器中的事件循环 (Event Loop)

Authors
  • avatar
    Name
    Tian Haipeng

同步 (synchronous)异步 (asynchronous)

在讨论事件循环前,我们需要先了解同步与异步的概念。JavaScript 是单线程的编程语言,代码按照顺序一行一行执行,称为同步 (synchronous)。然而,这种执行方式可能带来问题。比如,如果一段代码需要等待外部数据(如从服务器获取数据),这可能会导致页面长时间无法响应,给用户带来很差的体验。因此,JavaScript 引入了异步 (asynchronous) 概念。

异步代码不会阻塞主线程,主线程可以继续执行其他操作,直到异步任务完成后再处理它。正是通过事件循环的机制,JavaScript 才能够解决单线程的局限性,使耗时操作不会阻塞主线程。

事件循环 (Event loop) 的组成 - 执行栈和任务队列

事件循环本身并不存在于 JavaScript 内部,而是由 JavaScript 的执行环境(浏览器或 Node.js)实现的。它包括以下几个概念:

  • 堆 (Heap):用于存储对象的数据结构。
  • 栈 (Stack):后进先出(LIFO)数据结构。函数调用时会被推入栈顶,执行完后移出栈。
  • 队列 (Queue):先进先出(FIFO)数据结构。等待执行的任务会进入队列,等到栈空时再从队列取任务执行。
  • 事件循环 (Event loop):不断检查栈是否为空,若为空,则从队列取任务放入栈中执行。

事件循环的堆、栈和队列

事件循环的堆(Heap)、栈(Stack)和队列(Queue)

事件循环 (Event loop) 的步骤

事件循环的执行过程可以总结为以下几步:

  1. 所有任务在主线程上执行,形成一个执行栈。
  2. 如果遇到异步任务(如 setTimeout),执行环境会调用相关 API 处理,完成后再将任务放入任务队列中。
  3. 一旦执行栈中的所有同步任务完成,事件循环会从任务队列中取出第一个任务放入栈中执行。
  4. 事件循环会持续这个过程,直到所有任务完成。

宏任务 (Macro Task) 与微任务 (Micro Task)

JavaScript 的异步任务可以分为宏任务 (Macro Task) 和微任务 (Micro Task),它们的执行顺序不同。如果不区分这两类任务,代码的执行顺序可能会出乎意料。

例如,以下代码的输出顺序是什么?

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

如果仅考虑同步和异步,可能会认为输出顺序是 1234;但实际上正确答案是 1342。这是因为 Promise 任务属于微任务,而 setTimeout 属于宏任务。在一次事件循环中,宏任务只执行一个,之后会先执行微任务,因此 Promise 中的任务会先执行。

常见的宏任务和微任务如下:

  • 宏任务script(整体代码)、setTimeoutsetInterval、I/O、事件、postMessageMessageChannelsetImmediate (Node.js)。
  • 微任务Promise.thenMutationObserverprocess.nextTick (Node.js)。

执行顺序如下:

  1. 执行一次宏任务(最开始是整个 script,因此先执行 console.log(1))。
  2. 遇到宏任务时,放入宏任务队列。
  3. 遇到微任务时,放入微任务队列。
  4. 执行栈空时,先检查微任务队列,执行所有微任务。
  5. 执行浏览器渲染,接着开始下一个宏任务。

延伸:requestAnimationFramerequestIdleCallback

在事件循环面试题中,常涉及 requestAnimationFramerequestIdleCallback 的执行时机。requestAnimationFrame 在下次页面重绘之前执行,通常与页面渲染相关。而 requestIdleCallback 则会在浏览器有空闲时间时执行。

常见事件循环判断题

除了基础题目,面试中也常出现复杂的事件循环顺序判断题。可以通过分析事件循环、宏任务和微任务的执行顺序来解题。如果你想多做练习,可以参考《最常见的事件循环 (Event Loop) 面试题目汇总》一文。