🚀 事件循环在JavaScript中的作用和工作原理

📅 发布于 2026年1月 | 👤 作者:博主 | 🏷️ 标签:事件循环, Event Loop, 异步编程, JavaScript, 宏任务, 微任务, Web开发, 前端, 面试

欢迎来到我的博客文章!所有文章都是满满的前端干货,文章简明扼要。

JavaScript 是单线程语言,但通过 事件循环(Event Loop) 机制实现了高效的异步非阻塞 I/O 操作。这是 JS 能在浏览器和 Node.js 中处理大量并发任务(如网络请求、定时器、用户交互等)的核心原理。

一、事件循环的作用

💡 简单说:事件循环让 JavaScript "看起来"能同时做多件事,尽管它只有一个主线程。

二、核心组成部分

要理解事件循环,需先了解以下概念:

组件 说明
调用栈(Call Stack) 存放当前正在执行的函数(同步代码),后进先出(LIFO)
任务队列(Task Queue / Macro Task Queue) 存放宏任务(如 setTimeout、setInterval、I/O、UI 渲染等)的回调
微任务队列(Microtask Queue) 存放微任务(如 Promise.then/catch/finally、queueMicrotask、MutationObserver)的回调
事件循环(Event Loop) 不断检查调用栈是否为空,若空则从队列中取任务执行

三、工作原理(简化流程)

  1. 执行全局同步代码,压入调用栈。
  2. 遇到异步操作(如 setTimeout、fetch、Promise):
    • 宏任务(如 setTimeout)的回调放入 宏任务队列
    • 微任务(如 Promise.then)的回调放入 微任务队列
  3. 同步代码执行完毕,调用栈清空。
  4. 事件循环开始工作
    • 先清空微任务队列(全部执行完)
    • 再取一个宏任务执行(注意:一次只取一个!)
  5. 重复上述过程
✅ 关键规则:每次宏任务执行后,会立即执行所有可运行的微任务。

四、宏任务 vs 微任务

类型 常见来源
宏任务(Macro Task) setTimeout, setInterval, setImmediate(Node.js), I/O, UI 渲染(浏览器)
微任务(Microtask) Promise.then/catch/finally, queueMicrotask, MutationObserver, process.nextTick(Node.js,优先级更高)
⚠️ 注意:process.nextTick 在 Node.js 中比 Promise 微任务优先级更高,但在浏览器中不存在。

五、经典示例分析

console.log('1');

setTimeout(() => {
  console.log('2');
}, 0);

Promise.resolve().then(() => {
  console.log('3');
});

console.log('4');
输出顺序:1 4 3 2

解释:

六、浏览器中的渲染时机

在浏览器中,UI 渲染也是一个宏任务。事件循环在执行完一个宏任务 + 所有微任务后,可能进行一次页面重绘(如果需要)。

因此:

← 返回首页