生成器函数通过yield暂停执行,由调度器手动调用next()并处理Promise,实现“同步写法、异步执行”的流程控制;适用于需细粒度调度、状态机或框架底层场景,非async/await替代品。

JavaScript 中生成器函数本身不直接处理异步,但配合 next() 手动控制执行、搭配 Promise 和自定义调度器,可以实现清晰的异步任务调度逻辑。核心在于把异步操作“暂停”在 yield 处,由调度器决定何时恢复并传入结果。
用生成器暂停执行,交由调度器驱动
生成器函数返回一个迭代器,每次调用 next() 才执行到下一个 yield。这天然适合分步调度异步任务:
-
yield后面可以是 Promise(或任何值),但生成器不自动等待——需要调度器识别并await它 - 调度器拿到
{ value, done }后,若value是 Promise,就await完再调用next(result)把结果送回生成器内部 - 这样就实现了“写起来像同步,执行按需异步”的效果
手写一个简单调度器(co 风格)
下面是一个轻量级调度器,支持自动处理 Promise 类型的 yield 值:
function run(genFn) {
const gen = genFn();
<p>function next(data) {
const { value, done } = gen.next(data);
if (done) return value;</p><pre class="brush:php;toolbar:false;">if (value instanceof Promise) {
return value.then(res => next(res)).catch(err => gen.throw(err));
}
return next(value); // 非 Promise 直接递进}
return next(); }
使用示例:
function* fetchFlow() {
const user = yield fetch('/api/user');
const posts = yield user.json().then(u => fetch(`/api/posts?uid=${u.id}`));
return yield posts.json();
}
<p>run(fetchFlow).then(console.log); // 自动串行执行,无回调嵌套</p>
与 async/await 对比:适用场景不同
生成器调度不是为了替代 async/await,而是在特定场景更有表达力:
- 需要细粒度控制流程(如:每步前加日志、失败重试策略、条件跳过某步)
- 构建状态机或协程式任务流(比如游戏帧调度、表单多步骤校验)
- 与 Redux-Saga 等库配合,实现可撤销、可监听的副作用管理
- 学习运行时控制原理——
async/await底层正是基于生成器+状态机实现的
注意事项和常见坑
实际使用中要注意几个关键点:
-
yield后必须显式返回 Promise,否则调度器无法 await;普通值会立即传给下一次next() - 错误要用
gen.throw(err)注入,不能只靠try/catch—— 因为异步链中断后需手动恢复生成器状态 - 避免在生成器里混用
async函数(如async function*()是异步迭代器,用途不同) - 现代项目更推荐用
async/await或Promise.all并发控制;生成器调度更适合框架底层或定制化流程引擎
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











