async/await是promise的语法糖,现代引擎中独立实现、不依赖generator,仅语义相似;早期babel通过generator+自执行函数模拟,而v8等引擎采用挂起点与上下文切换机制直接优化。

async/await 本质上是 Promise 的语法糖,它底层并不直接依赖生成器(Generator),但早期在没有原生 async/await 支持时,Babel 等编译器确实曾用 Generator + 自执行函数 + Promise 模拟实现类似行为。不过需要明确:**现代 JavaScript 引擎中,async/await 是独立实现的语法特性,与 Generator 无运行时依赖关系;它的“类 Generator”感来自语义和执行模型的相似性,而非底层复用 Generator 机制。**
为什么容易联想到 Generator?
两者都表现出“暂停-恢复”特征:
- Generator 函数用 yield 暂停执行,外部通过 next() 恢复,并可传入值;
- async 函数用 await 暂停执行,等到 Promise settle 后自动恢复,并将 resolved 值返回给 await 表达式。
这种控制流让它们在代码形态和思维模型上高度相似,但实现路径不同。
Generator 模拟 async/await 的典型编译思路(历史方案)
在 ES2017 之前,Babel 的 transform-async-to-generator 插件会把 async 函数转成 Generator 函数,并用一个自调用的 runner 处理 yield 出来的 Promise:
用于 inference.sh 的 JavaScript/TypeScript SDK,可运行 AI 应用、构建代理、集成 150+ 模型。包名:@inferencesh/sdk(npm install),完整 TypeScript 支持。
- 把 async function → 编译为 function*;
- 把每个 await promise → 编译为 yield promise;
- 额外注入一个递归的 run(gen) 函数:调用
gen.next(value),捕获返回的{value, done};若 value 是 Promise,则.then(res => run(gen, res))继续推进。
这本质是手动调度 Generator 的执行,用 Promise 链驱动 next() 调用,从而模拟 await 的等待逻辑。
现代引擎的真实实现(不靠 Generator)
V8、SpiderMonkey 等引擎对 async/await 有专门优化:
- async 函数被解析为特殊函数类型,调用时直接返回 Promise 对象;
- 引擎在字节码层面为 await 插入“挂起点”,遇到 await 时保存当前执行上下文(包括栈帧、寄存器状态),将控制权交还事件循环;
- Promise resolve/reject 时,引擎从挂起点恢复上下文,继续执行后续代码——这个过程由运行时调度器完成,无需 Generator 迭代器接口参与。
也就是说,await 的暂停不是靠 yield 实现的,而是引擎级的协程式挂起(类似用户态线程的上下文切换),效率更高,也无需暴露迭代器对象。
关键区别总结
Generator 是语言提供的协作式控制流原语,需手动调度;async/await 是专为异步建模设计的语法,由引擎自动调度 Promise 状态变化。 它们共享“可暂停函数”的思想,但属于不同抽象层次:Generator 更通用(可用于惰性序列、状态机等),async/await 更专注(只服务异步 I/O 场景)。










