async函数是语法糖,JS引擎用状态机+Promise机制实现其暂停恢复行为,并非编译为Generator函数;它返回Promise,不可调用.next()或遍历,与Generator有语义相似但本质不同。

async 函数在底层并不是“被编译成”普通函数与 Generator 的组合,而是 JavaScript 引擎(如 V8)用 Generator + Promise 的语义模型来实现其行为,但实际执行时并不真的生成 Generator 函数代码。它是一种语法糖,运行时由引擎调度,而非源码层面转译为 Generator。
核心机制:状态机 + Promise 驱动
现代 JS 引擎(V8、SpiderMonkey 等)将 async 函数内部逻辑转换为一个隐式状态机,每个 await 表达式对应一个暂停点。引擎不生成用户可见的 Generator 函数,而是:
- 把 async 函数体拆解为多个微任务阶段(类似 Generator 的 next() 调用点)
- 每个 await 后的代码被包裹进 Promise.then 回调中,形成链式调用
- 引擎维护一个内部执行上下文,记录当前暂停位置、变量环境和 Promise 状态
为什么常被类比为 Generator + Promise?
因为从行为语义看,async/await 和 function* + yield + 手动 Promise 处理高度相似:
- 两者都支持函数中途暂停、等待异步结果后再恢复
- await x 等价于 yield new Promise(r => x.then(r))(手动模拟时)
- 早期 Babel(v6 及之前)确实用 Generator 模拟 async:把 async 函数重写为 function*,再用自动执行器(如 co)驱动,但这只是编译时降级,不是运行时本质
V8 中的真实处理流程(简化)
当你声明 async function foo() { await p; return 42; },V8 会:
立即学习“Java免费学习笔记(深入)”;
- 生成一个普通函数对象,但标记为 async 类型
- 在字节码层面插入 Suspend / Resume 指令,配合 Promise 状态切换
- 首次调用返回一个 Promise;遇到 await 时,将后续逻辑封装为 then 回调,并挂起当前执行帧
- Promise resolve 后,引擎从事件循环取出回调,在原函数上下文中继续执行(非新建调用栈)
关键区别:没有显式 Generator 实例
你无法对 async 函数调用 .next(),也不能用 for...of 遍历它——它不是 Generator 对象。它的暂停/恢复完全由引擎控制,不暴露迭代器接口。Generator 是可手动控制的惰性序列,async 函数是自动调度的一次性异步流程。
本质上,async 是语言级的异步抽象,引擎用更高效的方式(非 Generator 对象)实现了类似语义。理解它依赖 Generator 思维有助于掌握原理,但不要误以为源码里真有 yield 或生成了 * 函数。


















