【前端】JavaScript 的事件循环 (Event Loop)

JavaScript 的事件循环 (Event Loop ) 是其实现异步编程的核心机制,即使 JS 是单线程语言,它也能高效处理 I/O、网络请求、计时器等非阻塞操作。以下是其工作原理的精要解析:


核心概念

  1. 单线程执行

    • JS 引擎(如 V8)只能顺序执行一个任务。
    • 异步行为需要靠宿主环境(浏览器/Node.js)提供的事件循环调度。
  2. 任务队列 (Task Queue)

    • 所有异步操作完成后对应的回调函数会进入队列等待执行。
    • 队列类型包括:
      • 宏任务队列 (Macrotask Queue)script(整体代码)、setTimeoutsetInterval、DOM 事件回调、I/O 操作。
      • 微任务队列 (Microtask Queue)Promise.then()await后续代码、MutationObserverqueueMicrotask()

事件循环执行流程

  1. 执行同步代码

    运行主线程的同步任务,形成执行栈(Call Stack),若遇到异步操作(如 setTimeoutfetch),交给 Web API 处理。

  2. 异步任务回调入队

    异步操作完成后,Web API 将其回调推入对应队列:

    • 宏任务回调 → 宏任务队列
    • 微任务回调 → 微任务队列
  3. 轮询事件队列(关键步骤)

    • 执行完当前所有同步任务 后,按优先级处理队列:
      1. 清空微任务队列
        将所有可执行的微任务按顺序执行直至队列为空(执行中可能产生新微任务)。
      2. 执行一个宏任务
        从宏任务队列中取出最早的一个任务执行。
      3. 再次清空微任务队列
        执行该宏任务过程中产生的所有微任务。
      4. 更新渲染(浏览器环境下)
        如有需要,执行 UI 渲染、布局计算等。
    • 循环:重复步骤 3,直至所有队列为空。

执行顺序示例代码解析

javascript 复制代码
console.log("1. 同步代码开始");

setTimeout(() => {
  console.log("4. 宏任务 (setTimeout)");
}, 0);

Promise.resolve().then(() => {
  console.log("3. 微任务 (Promise)");
});

console.log("2. 同步代码结束");

输出顺序
1. 同步代码开始2. 同步代码结束3. 微任务 (Promise)4. 宏任务 (setTimeout)

原因

  • 先执行完所有同步代码(输出 1 和 2)。
  • 微任务队列优先于宏任务队列执行(Promise.then()setTimeout 前)。

为什么区分宏任务与微任务?

  • 微任务的优先级更高
    确保诸如 Promise 状态更新后能立即触发回调,提升用户体验(如快速响应用户操作)。
  • 避免渲染阻塞
    浏览器在宏任务之间插入 UI 渲染流程,而微任务在渲染前全部执行,保证页面及时更新。

事件循环流程图

复制代码
     同步代码执行
         ↓
  遇到异步操作 → Web API 处理 → 完成后回调入队
         ↓                      ↗ 宏任务队列
         |                     /
事件循环开始                 ↓
         |          下一轮循环  取出最早宏任务 → 执行
         |              ↑          ↓
         |------→ 清空微任务队列 → 可能产生新微任务
                       |
                   (浏览器环境下)
                        ↓
                    需要渲染? → 执行渲染流程

⚠️ 常见误区

  1. setTimeout(0) 并非立即执行
    定时器时间仅表示最小延迟,实际回调需等待同步任务及队列中的任务完成。
  2. 微任务会阻塞页面渲染
    长时间的微任务链会导致 UI 冻结。
  3. Node.js 与浏览器的事件循环差异
    Node.js 的事件循环分为更多阶段(如 nextTick 优先级最高)。

掌握事件循环机制,能帮你精准控制代码时序、避免竞态条件,并理解框架如 Vue/React 的底层调度原理!

相关推荐
这人是玩数学的2 分钟前
在 Cursor 中规范化生成 UI 稿实践
前端·ai编程·cursor
UncleKyrie3 分钟前
🎨 市面上主流 Figma to Code MCP 对比
前端
李明卫杭州5 分钟前
CSS `clamp()` 函数详解
javascript
奶丝兔蜜柚10 分钟前
栈溢出优化
javascript
南半球与北海道#16 分钟前
前端引入vue-super-flow流程图插件
前端·vue.js·流程图
然我22 分钟前
React 16.8:不止 Hooks 那么简单,这才是真正的划时代更新 🚀
前端·react.js·前端框架
小高00736 分钟前
📈前端图片压缩实战:体积直降 80%,LCP 提升 2 倍
前端·javascript·面试
OEC小胖胖39 分钟前
【React Hooks】封装的艺术:如何编写高质量的 React 自-定义 Hooks
前端·react.js·前端框架·web
BillKu1 小时前
vue3+element-plus 输入框el-input设置背景颜色和字体颜色,样式效果等同于不可编辑的效果
前端·javascript·vue.js