生成器函数是用 function* 声明的特殊函数,调用后返回迭代器对象,通过 next() 暂停/恢复执行并 yield 值;可配合 Promise 和执行器模拟 async/await 风格异步流程,但现已被原生 async/await 取代,多用于自定义迭代或框架底层(如 Redux-Saga)。

生成器函数是 JavaScript 中一种特殊的函数,它能暂停和恢复执行,配合 yield 关键字产出值。它本身不直接处理异步,但通过与 Promise、async/await 或自定义执行器协作,可构建出类似同步风格的异步流程。
生成器函数的基本特征
用 function* 声明,调用后返回一个迭代器对象(不是执行函数体),每次调用 next() 才运行到下一个 yield 并暂停。返回值是 { value, done } 形式的对象。
例如:
function* countdown(n) {while (n > 0) {
yield n;
n--;
}
}
const it = countdown(3);
it.next(); // { value: 3, done: false }
it.next(); // { value: 2, done: false }
it.next(); // { value: 1, done: false }
it.next(); // { value: undefined, done: true }
用生成器模拟 async/await 风格的异步流程
核心思路是:让生成器 yield 一个 Promise,外部执行器捕获该 Promise,等它 resolve 后再用 next(value) 把结果传回生成器继续执行。
立即学习“Java免费学习笔记(深入)”;
- 生成器内部写法接近同步:不用嵌套
.then,也不显式写await(但语义类似) - 需要手动或借助库(如
co)驱动执行,即反复调用next()并处理 Promise - 错误可通过
it.throw(err)注入生成器内部,配合try/catch捕获
简易执行器示例:
function run(genFn) {const it = genFn();
function next(val) {
const { value, done } = it.next(val);
if (done) return value;
if (value instanceof Promise) {
return value.then(next).catch(err => it.throw(err));
} else {
return next(value);
}
}
return next();
}
// 使用:
run(function* () {
const user = yield fetch('/api/user').then(r => r.json());
console.log(user.name);
const posts = yield fetch(`/api/posts?uid=${user.id}`).then(r => r.json());
return posts;
});
与现代 async/await 的关系
生成器曾是实现协程式异步的主流方案(尤其在 async/await 出现前),但现在已被原生 async/await 取代:
-
async/await语法更简洁,错误处理更自然,引擎级优化更好 - 生成器现在更多用于需精细控制迭代逻辑的场景(如惰性序列、状态机、遍历树结构)
- 少数库仍基于生成器实现高级控制流(如 Redux-Saga 中的
takeEvery、call等 effect)
实际建议
日常开发中无需主动用生成器写异步逻辑:
- 优先使用
async/await—— 语义清晰、调试友好、浏览器支持完善 - 理解生成器原理有助于读懂老项目或特定框架(如 Saga)的源码
- 若需自定义迭代行为(比如分页拉取、无限滚动的数据流),生成器 +
yield是天然选择











