async/await 是 generator 与 promise 结合的语法糖,本质是自动调度的 generator:async 函数编译为状态机,await 对应 yield 并自动处理 promise 的 resolve/reject,实现异步代码同步化书写。

Generator 本身不直接配合 async/await 运行,它其实是 async/await 的“前身”和底层思想来源。理解 Generator,就是理解 async/await 为什么长这样、为什么能写得像同步代码——它不是替代关系,而是演进关系。
Generator 是“可暂停的函数”,为异步流程建模打下基础
普通函数一旦开始执行,就会一路跑到 return 或结束;而 Generator 函数用 function* 声明,调用后不执行,只返回一个迭代器。真正执行靠 next(),遇到 yield 就暂停,并把值交出来。
- 暂停点天然对应异步等待位置:比如
yield fetch('/api/user')表示“这里等请求回来再继续” - next(value) 能把上一步的结果传进去,实现数据流动:“请求返回了,把 response 给下一步用”
- 整个执行过程由外部控制(比如手写递归或借助 co 库),相当于把调度权交给了开发者
async/await 是 Generator + Promise 的自动调度封装
手动用 Generator 写异步,要反复调 next()、接 then()、判断 done,非常繁琐。async/await 把这套流程完全内置了:
- async 函数 = 自动执行的 Generator:引擎内部把它编译成类似 Generator + 状态机的形式
- await = yield + 自动 resolve/reject 处理:它会等 Promise settle 后,把结果自动传给下一步,不再需要手动 next(value)
- 错误统一用 try/catch 捕获,不用像 Generator 那样手动 throw 到迭代器里
从手动调度到自动调度,是语法糖背后的关键跃迁
早期有人用 Generator + Promise + co 库模拟 async/await:
function* main() {<br> const user = yield fetch('/user').then(r => r.json());<br> const posts = yield fetch(`/posts?uid=${user.id}`).then(r => r.json());<br> return { user, posts };<br>}<br>co(main).then(console.log);这段代码逻辑清晰,但依赖第三方库、要自己处理 Promise 链、还要记住 co 的规则。async/await 把这些全部收进语言标准:
- 去掉
function*和yield,改用async function和await - 引擎自动识别 await 后的 Promise,挂起当前函数,等它 settled 后恢复执行
- 微任务队列(microtask queue)保证 await 后续代码在当前宏任务结束后立即执行,语义更确定
理解演进史,关键不在“怎么用”,而在“为什么这样设计”
回调地狱 → Promise(解决嵌套)→ Generator(解决书写方式)→ async/await(解决调度负担)
- Promise 解决了“能不能扁平化”,但仍是 .then 风格,思维仍要绕着链走
- Generator 解决了“能不能像同步一样写”,但把调度复杂度甩给了开发者
- async/await 解决了“能不能既像同步写,又不用管调度”,把最佳实践变成语言原生能力
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











