生成器本身不是协程,但它是实现协程的底层机制——关键在于用yield暂停执行,并由外部调度器控制恢复时机和传入数据;它提供暂停与恢复、双向通信、状态保持三项能力,需手动调度器驱动异步流程。

生成器本身不是协程,但它是实现协程的底层机制——关键在于用 yield 暂停执行,并由外部调度器控制恢复时机和传入数据。这种“主动让出 + 协作恢复”的模式,正是协同程序(Coroutine)的本质。
生成器如何承载协程语义
生成器函数返回一个迭代器对象,每次调用 next() 或 send() 时,它从上次 yield 处继续运行,可接收参数、产出值、抛出异常。这提供了协程所需的三项能力:
-
暂停与恢复:遇到
yield自动挂起,下次调用next()继续 -
双向通信:用
yield x向外传值,用send(y)向内传参 - 状态保持:函数局部变量、执行位置等全部保留在生成器对象内部
手动调度:写一个简单执行器
要让生成器真正处理异步流,需一个执行器(runner)来识别 yield 出的 Promise(或类似可等待对象),等待其完成后再恢复生成器。例如:
JavaScript 示例
function run(genFn) {
const gen = genFn();
function next(data) {
const { value, done } = gen.next(data);
if (done) return value;
return value.then(next); // 自动 await yield 出的 Promise
}
return next();
}
这样就能写出看似同步、实则异步的逻辑:
run(function* () {
const user = yield fetch('/api/user');
const posts = yield fetch(`/api/posts?uid=${user.id}`);
console.log(posts);
});
复用已有生态:co 库与 async/await 的桥梁
像 JavaScript 的 co 库、Python 早期的 asyncio.coroutine(基于 yield from),都是这类执行器的成熟封装。它们统一处理:
- 自动展开嵌套 Promise / 可等待对象
- 错误冒泡到生成器内部的
try/catch - 支持
return值作为最终 Promise 结果
这些工具让生成器协程成为 async/await 出现前最接近同步风格的异步写法,也解释了为什么 async/await 在设计上大量借鉴了生成器协程的语义。
适用场景:何时值得用生成器协程
不是所有异步都适合——它优势在可控的复杂流程编排,比如:
- 多步骤 API 调用,中间需条件分支或重试逻辑
- 状态机驱动的交互流程(如 OAuth 授权链、表单向导)
- 需要精确控制每一步暂停点的调试/回放系统
- 与现有生成器生态集成(如惰性数据流 + 异步 I/O)
若只是单个请求,async/await 更直接;若涉及大量并发协调,asyncio.gather 或 Promise.all 更合适。生成器协程的价值,在于把“流程控制权”交还给开发者。










