JavaScript是单线程语言,同一时间只能执行一个任务,为了不阻塞主线程,异步任务会被放到特定队列中等待执行,而Event Loop就是负责调度这些异步任务执行的核心机制,它直接决定了异步代码的执行顺序和时机。

Event Loop的基本运行逻辑
Event Loop的运行依赖三个核心部分:调用栈、宏任务队列、微任务队列。它的基本执行流程如下:
- 首先执行当前同步代码,遇到函数调用就压入调用栈,执行完成后弹出
- 同步代码全部执行完成后,检查微任务队列,依次执行所有微任务,直到微任务队列清空
- 微任务执行完成后,从宏任务队列取出第一个任务执行,执行完后再次检查微任务队列,重复上述流程
宏任务与微任务的分类
JavaScript中的异步任务分为宏任务和微任务两类,不同类型的任务会被放到不同的队列中,执行优先级也有区别:
| 任务类型 | 常见示例 |
|---|---|
| 宏任务 | setTimeout、setInterval、script整体代码、I/O操作、UI渲染 |
| 微任务 | Promise.then/catch/finally、process.nextTick(Node环境)、queueMicrotask |
结合示例理解执行顺序
我们可以通过一段代码来验证Event Loop的执行规则,代码如下:
console.log('同步代码1'); // 同步代码,直接执行
setTimeout(() => {
console.log('宏任务setTimeout'); // 宏任务,放到宏任务队列
}, 0);
Promise.resolve().then(() => {
console.log('微任务Promise1'); // 微任务,放到微任务队列
}).then(() => {
console.log('微任务Promise2'); // 微任务,上一个then执行完后加入微任务队列
});
console.log('同步代码2'); // 同步代码,直接执行
这段代码的执行结果依次是:同步代码1、同步代码2、微任务Promise1、微任务Promise2、宏任务setTimeout。原因是同步代码先执行完,然后清空微任务队列,最后才执行宏任务队列里的任务。
为什么Event Loop是异步编程的关键
很多异步编程中的常见困惑都能通过Event Loop解释:
- 为什么
setTimeout的延迟时间不精准?因为setTimeout只是把任务放到宏任务队列,需要等前面的同步代码、微任务都执行完才会执行 - 为什么Promise的回调比
setTimeout先执行?因为Promise的回调属于微任务,优先级高于宏任务 - 为什么多个Promise的then会连续执行?因为每个then的回调执行后如果返回新的Promise,新的then回调会被加入当前微任务队列,会在同一轮微任务清空阶段执行
如果不理解Event Loop,写异步代码时很容易对执行顺序判断错误,比如想要先执行某个异步操作再执行另一个,却因为任务类型放错导致顺序不符合预期。掌握Event Loop后,就能准确预判任意异步代码的执行结果,也能合理设计异步逻辑的执行顺序,避免各类异步相关的问题。
注意:不同运行环境的Event Loop细节可能有差异,比如浏览器和Node.js的宏任务执行顺序略有不同,但核心的调用栈、宏任务微任务调度逻辑是一致的。
Event_LoopJavaScript异步编程宏任务微任务修改时间:2026-07-23 21:18:30