同步生成器就是普通的 function*,它返回一个 Generator 对象。这个对象既是迭代器,也是可迭代对象。
手工遍历的核心就是反复调用 it.next(),直到 done 为 true。
1. 基本写法
ts
function* gen(): Generator<number, void, unknown> {
yield 1;
yield 2;
yield 3;
}
手动遍历:
ts
const it = gen();
let result = it.next();
while (!result.done) {
console.log(result.value); // 1, 2, 3
result = it.next();
}
console.log(result.done); // true
关键点:
function*调用后不会执行函数体,而是返回生成器对象。it.next()返回IteratorResult<T>,同步生成器不需要await。- 每次
next()执行到下一个yield。 done: false时,value是yield出来的值。done: true时,生成器结束。
2. 带 return 返回值
生成器可以通过 return 返回最终值:
ts
function* gen(): Generator<number, string, unknown> {
yield 1;
yield 2;
return "结束";
}
const it = gen();
let result = it.next();
while (!result.done) {
console.log(result.value); // 1, 2
result = it.next();
}
console.log(result.value); // "结束"
console.log(result.done); // true
注意:
for...of 遍历时不会拿到 return 的返回值,但手动 next() 可以拿到。
3. 手动传值
可以通过 next(value) 把值传回生成器内部的 yield 表达式:
ts
function* dialog(): Generator<string, void, string> {
const name = yield "请输入姓名:";
yield `你好,${name}`;
}
const it = dialog();
console.log(it.next());
// { value: "请输入姓名:", done: false }
console.log(it.next("Tom"));
// { value: "你好,Tom", done: false }
console.log(it.next());
// { value: undefined, done: true }
关键点:
- 第一次
next()的参数会被忽略。 - 第二次
next("Tom")的值会作为上一个yield表达式的返回值,赋给name。
4. 提前终止和清理
生成器内部可以写 try/finally:
ts
function* gen(): Generator<number, void, unknown> {
try {
yield 1;
yield 2;
yield 3;
} finally {
console.log("清理资源");
}
}
const it = gen();
console.log(it.next()); // { value: 1, done: false }
console.log(it.return()); // 触发 finally,输出"清理资源"
// { value: undefined, done: true }
it.return(value) 会提前结束生成器,并执行 finally。
it.throw(error) 可以向生成器内部抛异常。
5. 完整手动遍历模板
ts
function* gen(): Generator<number, string, unknown> {
yield 1;
yield 2;
return "done";
}
const it = gen();
let result = it.next();
while (!result.done) {
const value = result.value; // number
console.log(value);
result = it.next();
}
const returnValue = result.value; // string
console.log(returnValue);
总结
同步生成器手工遍历就是:
ts
const it = gen();
let result = it.next();
while (!result.done) {
console.log(result.value);
result = it.next();
}
不需要 await,因为 next() 直接返回结果,而不是 Promise。
如果需要控制每一步、传值、提前终止或获取 return 值,就用手动 next();如果只是简单消费所有 yield 值,用 for...of 更方便。