【前端】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 的底层调度原理!

相关推荐
Sterting几秒前
Element-Plus 入门与整体布局
前端·vue.js·elementui
程序员黑豆7 小时前
Java 注释详解:单行、多行与文档注释的完整指南
java·前端·ai编程
剪刀石头布啊7 小时前
antd中可编辑表格中巧用useWatch实现联动高性能效果,以及定制延伸学习
前端
油丶酸萝卜别吃8 小时前
前端转全栈学习路线
前端·学习
浮生望8 小时前
前端路由进阶:History API原理与手写HistoryRouter
前端
wuyk5558 小时前
第2章:六步换相原理全解+STM32工程实战
c语言·开发语言·stm32·单片机·嵌入式硬件
hey_sml8 小时前
JAVA每日一学---CompletableFuture中thenApply与thenCompose区别详解
java·开发语言
陆枫Larry9 小时前
JavaScript 中的竞态是什么,为啥会有竟态?
前端
萧瑟余晖10 小时前
Java深入解析篇十七之SpringCloud
java·开发语言
上海安当技术11 小时前
半天接入:USBKey RESTful API + C 动态库,Web 和 C/S 两套集成路径实战
前端·后端·restful·集成·usbkey