一、介绍
JavaScript 是单线程的,事件循环就是它用来“协调异步任务执行”的机制。这里还要介绍一下栈(Stack)和队列(Queue)。
1.Call Stack,调用堆栈

JS的Call Stack是一种经典的栈结构,它的特点是后进先出(last in first out,LIFO),下面例子可以解释:
function a() {
b();
}
function b() {
c();
}
function c() {
console.log("Hello");
}
a();
调用顺序:
Call Stack:
→ c
→ b
→ a
2.Task Queue,任务队列
任务队列(Task Queue)是指在事件循环中等待执行的异步回调任务的集合,包含宏任务队列(Macrotask Queue)和微任务队列(Microtask Queue)。这些任务会在主线程空闲(同步代码执行完)后被依次执行,确保 JavaScript 单线程环境中的异步操作可以“有序排队”。
3.事件循环的执行流程
- 执行主线程代码(立即执行同步任务)
- 检查异步任务队列(宏任务队列 / 微任务队列)
- 取出任务执行
- 当前宏任务执行完之后立即执行 微任务
- 下一轮事件循环中执行 宏任务
- 重复执行这个循环
二、常见任务类型
任务类型 | 示例 | 队列类型 |
同步任务 | 普通代码 | 主线程直接执行 |
微任务 (Microtask) | Promise.then Promise.catch Promise.finally window.queueMicrotask 浏览器创建微任务API await的后续代码包装为微任务 | 微任务队列(优先),在当前同步任务之后执行 |
宏任务 (Macrotask) | setTimeout 下一个事件循环 setInterval setImmediate requestAnimationFrame 浏览器执行动画API,下一帧渲染前执行回调 DOM 事件(click, input, keydown, load, scroll 等用户交互事件) | 宏任务队列,执行一次循环之后,排在下一个宏任务中执行 |
三、await对事件循环的影响
当被 await 的 Promise 解决时,后续代码会作为微任务加入队列,等价于把后续代码放进Promise.then()中。
async function foo() {
console.log(1);
await bar();
// 后续代码被包装为微任务
// 等foo函数后的同步任务执行完才会执行微任务
console.log(3);
}
function bar() {
console.log(2);
}
foo();
console.log(4);
// 输出顺序: 1 → 2 → 4 → 3
每个 await 都会创建新的微任务,需要注意在微任务队列中的层级关系。
// 使用 .then()
Promise.resolve()
.then(() => console.log('then 1')) // 第1层第1个微任务
.then(() => console.log('then 2')); // 第2层第1个微任务
// 使用 await
(async () => {
await Promise.resolve(); // 下面三行包装为第1层第2个微任务
console.log('await 1');
await Promise.resolve(); // 下面一行包装为第2层第2个微任务
console.log('await 2');
})();
// 输出顺序:
// then 1 → await 1 → then 2 → await 2
四、案例题目
console.log("start")
setTimeout ( ()=>{
console.log ('timer1')
new Promise (function (resolve){
console.log(" promise start ")
resolve ();
}).then (function () {
console. log('promise1')
// 注意:如果这里还有一个setimeout,那么输出将在promise2之后
})
},0)
setTimeout (() =>{
console.log( 'timer2')
Promise.resolve( ).then(function() {
console. log('promise2')
})
},0)
console. log("end")
结果:
start // 同步
end // 同步
timer1 // 第一个宏任务中的同步任务
promise start // 第一个宏任务中的同步任务 new Promise(...)
promise1 // 第一个宏任务中的微任务
timer2 // 第二个宏任务的同步任务
promise2 // 第二个宏任务的微任务