浏览器的事件循环详解

浏览器的事件循环详解
最新回答
浅夏忆梦

2026-04-09 16:49:32

浏览器的事件循环是负责执行代码、收集和处理事件以及执行队列中子任务的核心机制,其运行流程基于执行上下文栈、任务队列(宏任务与微任务)的协作,具体如下:

执行上下文栈
JavaScript代码执行时,会进入不同的执行环境(如全局环境、函数环境),每个环境对应一个执行上下文。全局上下文首先被创建并入栈,调用函数时,函数上下文入栈;栈顶上下文执行完毕后出栈。栈的结构决定了代码的执行顺序,遵循“后进先出”原则。

任务队列的分类与优先级
任务队列分为宏任务队列和微任务队列,两类任务在事件循环中的处理顺序不同:

  • 宏任务:包括setTimeout、setInterval、I/O操作、UI渲染等。这类任务通常由浏览器外部事件触发,优先级较低。
  • 微任务:包括Promise、MutationObserver(已废弃的Object.observe不纳入讨论)。微任务由JavaScript内部逻辑触发,优先级高于宏任务。

事件循环的核心流程

  1. 主线程执行同步代码:主线程从全局上下文开始,逐行执行JavaScript代码,形成执行上下文栈。遇到异步任务(如setTimeout、Promise)时,将其挂起,不立即执行。
  2. 异步任务分发至任务队列:当异步任务完成(如定时器到期、Promise状态变更),浏览器将其放入对应的任务队列:微任务进入微任务队列,宏任务进入宏任务队列。
  3. 清空微任务队列:执行上下文栈清空(仅剩全局上下文)后,事件循环优先处理微任务队列。所有微任务按“先进先出”顺序执行,直到队列为空。
  4. 处理宏任务队列:微任务队列清空后,事件循环从宏任务队列中取出优先级最高的任务(如setTimeout),按“先进先出”顺序执行一个宏任务。
  5. 循环交替执行:重复步骤3-4,交替清空微任务队列和宏任务队列,直至所有队列为空,最后全局上下文出栈,程序结束。

关键注意事项

  • 微任务优先级:微任务会在当前宏任务结束后、下一个宏任务开始前全部执行完毕,因此可能阻塞渲染(如大量微任务会导致UI更新延迟)。
  • Node.js与浏览器的差异:Node.js的事件循环基于libuv实现,与浏览器机制不同(如setImmediate为Node特有宏任务),需区分应用场景。