01 事件循环机制 Event Loop
JS 是单线程的,但通过 Event Loop 实现了"假装多任务"——同步代码先跑完,然后处理微任务,最后处理宏任务,不断循环。
![[Screenshot 2026-03-16 at 12.33.38 PM.png]]
事件循环的组成部分¶
事件循环主要由以下几个部分组成: - 执行栈(Call Stack):当前正在执行的代码所在的栈。当函数被调用时,它会被推入执行栈;当函数执行完毕时,它会从执行栈中弹出。 - 当前正在跑的代码 - 事件队列(Event Queue)/宏任务队列(Macrotask Queue):存储异步事件的队列。当异步操作(如Ajax请求、定时器等)完成时,相关的回调函数会被放入事件队列中等待执行。 - setTimeout、setInterval、Ajax(优先级低) - 微任务队列(Microtask Queue):存储微任务的队列。微任务是在当前执行栈清空后,事件循环开始之前执行的任务。它们通常用于处理Promise回调等需要快速执行的轻量级任务。 - Promise.then、queueMicrotask(优先级高) 执行栈空了 → 把微任务队列全部清完 → 取宏任务队列里一个出来跑 → 再清微任务 → 循环
事件循环的过程¶
(1)执行代码:JavaScript引擎执行同步代码,并将函数调用放入执行栈中。 (2)处理微任务:当执行栈为空时,事件循环会检查微任务队列,并执行其中的回调函数,直到微任务队列为空。 (3)处理事件:微任务队列处理完毕后,事件循环会检查事件队列,并执行其中的回调函数,直到事件队列为空。 (4)重复步骤2和3:事件循环会不断重复这个过程,直到执行栈、微任务队列和事件队列都为空。
例子¶
console.log("开始");
setTimeout(() => {
console.log("setTimeout");
}, 0);
Promise.resolve()
.then(() => {
console.log("第一个then");
})
.then(() => {
console.log("第二个then");
});
console.log("结束");
// 输出:
// 开始
// 结束
// 第一个then
// 第二个then
// setTimeout
- 开始和结束都是同步,直接跑
setTimeout的回调进宏任务队列Promise.then的回调进微任务队列- 同步跑完,先清微任务 → 打印 第一个then 第二个then
- 两个
.then都是微任务,会连续清完,才轮到 setTimeout。