Generator函数是通过function*定义并返回迭代器的对象,利用yield暂停执行和next()恢复运行,实现异步控制与惰性求值,支持双向通信及错误处理,适用于状态机、无限序列生成等场景。
Generator函数是javaScript中一种特殊的函数类型,能够实现函数的暂停与恢复执行,为异步编程和迭代控制提供了强大支持。它不像普通函数那样一次性运行完毕,而是可以在执行过程中多次暂停,并在需要时继续执行。
什么是Generator函数
Generator函数通过 function* 语法定义,调用后返回一个遍历器对象(Iterator),该对象遵循迭代器协议,具备 next() 方法来逐步驱动函数体内的执行。
函数内部使用 yield 关键字来定义暂停点。每次调用 next(),函数会从上次暂停处继续运行,直到遇到下一个 yield 或函数结束。
示例:
立即学习“Java免费学习笔记(深入)”;
function* myGenerator() {
console.log(“第一步”);
yield “A”;
console.log(“第二步”);
yield “B”;
console.log(“完成”);
return “结束”;
}
const gen = myGenerator();
gen.next(); // 输出”第一步”,返回 { value: “A”, done: false }
gen.next(); // 输出”第二步”,返回 { value: “B”, done: false }
gen.next(); // 输出”完成”,返回 { value: “结束”, done: true }
yield与next的交互机制
yield 不仅用于输出值,还可以接收外部传入的数据。通过 next(value) 方法,可以向 Generator 函数体内传递参数,实现双向通信。
注意:第一次调用 next() 通常不建议传参,因为没有对应的 yield 接收初始值(除非特别设计)。从第二次开始,传入的值会替换上一个 yield 表达式的返回结果。
示例:双向数据传递
function* counter() {
let count = 0;
while (true) {
const reset = yield count++;
if (reset) count = 0;
}
}
const iter = counter();
iter.next(); // { value: 0, done: false }
iter.next(); // { value: 1, done: false }
iter.next(true); // { value: 0, done: false },重置计数
return与throw方法
除了 next(),Generator 实例还提供 return() 和 throw() 方法来控制流程。
- return(value):结束生成器执行,返回指定值,并使 done 为 true。后续 yield 将不再生效。
- throw(Error):在暂停点抛出异常,可在函数内使用 try…catch 捕获处理。
示例:提前终止与错误处理
function* errorDemo() {
try {
yield “正常执行”;
} catch (e) {
console.log(“捕获错误:”, e.message);
}
}
const g = errorDemo();
g.next(); // { value: “正常执行”, done: false }
g.throw(new Error(“出错了”)); // 控制台输出“捕获错误: 出错了”
应用场景与实际用途
虽然现代异步主要依赖 async/await,但 Generator 在特定场景仍有价值。
- 惰性求值序列:生成无限序列(如斐波那契数列),按需计算。
- 状态机:利用 yield 切换状态,逻辑清晰。
- 中间件流程控制:Koa1 使用 Generator 实现洋葱模型,虽然后续版本改用 promise。
- 测试模拟异步流程:便于控制执行节奏。
示例:无限斐波那契生成器
function* fibonacci() {
let [prev, curr] = [0, 1];
while (true) {
yield curr;
[prev, curr] = [curr, prev + curr];
}
}
const fib = fibonacci();
fib.next().value; // 1
fib.next().value; // 1
fib.next().value; // 2
fib.next().value; // 3
// 可持续调用,按需生成
基本上就这些。Generator 提供了对函数执行的精细控制能力,理解其机制有助于深入掌握 javascript 的执行模型和异步原理。虽然日常开发中使用不多,但在底层库或复杂控制流中仍具实用价值。