Generator函数调用不执行,只返回遍历器对象;必须手动调用next()推进,yield后Promise需显式处理,自动执行器run()可递归调度但已被async/await全面替代。

Generator 协程为什么不能直接运行
调用 function* 只返回一个生成器对象,它不会自动执行,也不会自动处理 yield 后的 Promise。你必须手动调用 next(),并在 Promise resolve 后再次调用 next(value) 把结果传回去——这正是“不能直接运行”的根源。
常见错误现象包括:
-
gen.next().value返回一个 pendingPromise,但后续没接.then(),导致流程卡死 - 忘记把异步结果传给下一次
next(),yield接收值始终为undefined - 未处理
throw()或return(),异常被吞掉,调试时找不到报错位置
如何写一个最小可用的自动执行器 run()
核心逻辑是:递归调用 next(),遇到 Promise 就 .then() 继续推进,直到 done: true。不需要第三方库,10 行内可实现。
实操建议:
- 执行器接收一个 Generator 函数(不是实例),内部先调用它得到
gen - 定义
function next(data)递归函数,每次调用gen.next(data) - 若
result.done为true,直接返回result.value - 若
result.value是 Promise,用.then(res => next(res))拆包并继续 - 注意捕获 Promise rejection,用
.catch(err => gen.throw(err))向生成器抛错
示例:
function run(genFn) {
const gen = genFn();
function next(data) {
const result = gen.next(data);
if (result.done) return result.value;
if (result.value instanceof Promise) {
return result.value.then(res => next(res)).catch(err => gen.throw(err));
}
return next(result.value);
}
return next();
}
yield 后能接什么?类型和兼容性要注意什么
yield 后不只限于 Promise;它可以是任意值,但自动执行器只对 Promise 做等待处理。其他类型会立即传回给下一次 next(),相当于同步流转。
使用场景与差异:
- 接
Promise:标准异步协程行为,如yield fetch('/api') - 接普通对象/数组/字符串:立刻继续,适合做中间状态或调试断点
- 接另一个 Generator(需
yield*):执行器默认不支持委托,除非你显式判断result.value是 Generator 并递归 run 它 - Node.js 14+ 和现代浏览器都支持,但 IE 完全不支持
function*,别在需要兼容老环境的项目里用
为什么现在很少人真用 Generator 协程调度器
不是它不能用,而是 async/await 在语义、错误处理、工具链支持上全面胜出。V8 引擎对 async 的优化比 Generator 高出 20%–30%,TypeScript 对 async 的类型推断也更自然。
容易被忽略的关键点:
- Generator 执行器无法原生支持
await,你不能在function*里写await,只能靠yield+ 外部执行器模拟 - 调试体验差:堆栈追踪显示的是执行器的
next()调用,而不是原始yield行号 - 生态脱节:主流 HTTP 库、状态管理方案、测试工具都面向
async设计,Generator 需额外封装层
除非你在写底层调度框架、学习编译原理,或维护一段历史代码,否则直接用 async function 更省力也更健壮。










