
本文深入解析 async/await 在 JavaScript 执行上下文和事件循环中的实际行为,阐明为何 console.log("End") 会早于 await 后的 console.log("Hello") 执行,并清晰还原函数调用、微任务入队与执行的完整时序。
本文深入解析 async/await 在 javascript 执行上下文和事件循环中的实际行为,阐明为何 console.log("end") 会早于 await 后的 console.log("hello") 执行,并清晰还原函数调用、微任务入队与执行的完整时序。
我们来逐步拆解这段代码的执行流程,结合调用栈(Call Stack)、任务队列(Task Queue)和微任务队列(Microtask Queue),理解其底层行为:
let hello = () => Promise.resolve("Hello");
async function fun() {
console.log("Inside");
const result = await hello(); // ⚠️ 暂停点:不阻塞主线程,返回 Promise 并让出控制权
console.log(result);
}
console.log("Start");
fun(); // → 立即返回一个 pending 状态的 Promise,fun 开始执行但不阻塞后续
console.log("End");✅ 执行时序详解(按时间顺序)
-
同步阶段(宏任务第 1 轮)
-
console.log("Start")→ 输出"Start" -
fun()被调用:-
fun入栈 → 执行console.log("Inside")→ 输出"Inside" - 遇到
await hello():hello()返回Promise.resolve("Hello")(即已 fulfilled 的 Promise) -
await将后续逻辑(console.log(result))封装为微任务(microtask),并立即返回控制权给调用者(此时fun函数体暂停,但不退出栈;它返回一个 pending Promise 给外部) -
fun出栈(注意:不是“等待完才出栈”,而是“await 后立即出栈”)
-
-
console.log("End")→ 输出"End" - 同步代码执行完毕,第一轮宏任务结束。
-
-
微任务清空阶段(紧随宏任务之后)
- 浏览器检查微任务队列:发现由
await产生的微任务(即console.log(result)) - 执行该微任务 → 输出
"Hello"
- 浏览器检查微任务队列:发现由
? 关键点:
await不会阻塞整个 JS 主线程,它只暂停当前async函数内部的同步执行流,并将剩余逻辑注册为微任务;而外部同步代码(如console.log("End"))照常运行。
Alibabacloud Sdk Client Initialization For Java下载在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
? 补充说明:为什么 fun() 调用后立即返回?
-
async function的本质是语法糖:它自动将函数体包装进Promise,并把await后续逻辑通过Promise.then()注册为微任务。 -
fun()调用后,无论内部是否有await,都立刻返回一个 Promise 对象(初始状态为pending),因此绝不会造成同步阻塞。
你可以用等价的 Promise 写法验证:
function funEquivalent() {
console.log("Inside");
return hello().then(result => {
console.log(result); // 这行等同于 await 后的语句
});
}执行效果完全一致:"Start" → "Inside" → "End" → "Hello"。
⚠️ 注意事项
-
await只对当前async函数内部有效,对外部调用者而言,async函数始终是“立即返回 Promise”的异步操作。 - 若需确保
"End"在"Hello"之后打印,必须让外部也参与异步等待:console.log("Start"); await fun(); // ❗需在 async 上下文中使用 console.log("End"); - 所有
await后的表达式(包括Promise.resolve())都会被 Promise 化;若返回非 Promise 值,会被自动包装为Promise.resolve(value)。
✅ 总结
JavaScript 的 async/await 是基于 Promise 和微任务的语法糖,其核心设计哲学是非阻塞式异步控制流。await 暂停的是函数内部执行,而非线程或调用栈;真正的“等待”发生在微任务阶段,且严格遵循「同步 → 微任务 → 下一轮宏任务」的事件循环规则。理解这一点,是掌握 JS 异步编程的关键基石。


















