2803. 生成器函数
2025年6月25日大约 2 分钟
2803. 生成器函数
function* factorial(n) {
if(n===0) return 1;
let result = 1;
for (let i = 1; i <= n; i++) {
result *= i;
yield result; // 每次产出 i! 的值
}
}
✅ 什么是生成器?
生成器函数是 ES6
引入的一种函数类型,可以 在执行过程中暂停,并在之后继续执行。这种特性使其非常适合实现迭代器、异步控制流、惰性求值等场景。
🧬 语法基础
function* generatorName([param1, param2, ...]) {
yield value1;
yield value2;
return finalValue;
}
function*:星号表示这是一个生成器函数
yield:关键字,用来“产出”值并暂停执行
.next():继续执行到下一个 yield
return 不会在 for...of 中被遍历到
yield 可以接收值和产出值
调用生成器函数不会立即执行,必须通过 .next() 启动
yield*(委托另一个生成器)
function* inner() {
yield "A";
yield "B";
}
function* outer() {
yield "Start";
yield* inner(); // 委托 inner 的产出
yield "End";
}
for (const val of outer()) {
console.log(val); // Start, A, B, End
}
yield 可传值
function* dialogue() {
const answer1 = yield "你是谁?";
const answer2 = yield "你从哪里来?";
return `你好,${answer1},来自${answer2}`;
}
const gen = dialogue();
console.log(gen.next().value); // "你是谁?"
console.log(gen.next("小明").value); // "你从哪里来?"
console.log(gen.next("北京").value); // "你好,小明,来自北京"
实现自定义迭代器
const iterable = {
*[Symbol.iterator]() {
yield 10;
yield 20;
yield 30;
}
};
for (const val of iterable) {
console.log(val); // 10, 20, 30
}
依赖函数队列(重试,超时)
const taskFns = [
async () => {
console.log("任务1开始");
return "结果1";
},
async (prevResult) => {
console.log("任务2接收到:", prevResult);
if (Math.random() < 0.7) throw new Error("任务2随机失败");
return prevResult + " → 结果2";
},
async (prevResult) => {
console.log("任务3接收到:", prevResult);
return prevResult + " → 结果3";
}
];
function* retryableTaskQueue(taskFns, maxRetries = 3, delay = 1000) {
let lastResult = undefined;
for (let i = 0; i < taskFns.length; i++) {
let attempt = 0;
while (attempt < maxRetries) {
try {
const result = yield taskFns[i](lastResult); // 将前一个结果传入
lastResult = result; // 保存供下一个用
break; // 当前任务成功,进入下一个任务
} catch (err) {
attempt++;
console.warn(`任务 ${i + 1} 第 ${attempt} 次尝试失败:`, err.message);
if (attempt >= maxRetries) {
throw new Error(`任务 ${i + 1} 已超过最大重试次数`);
}
yield new Promise(res => setTimeout(res, delay)); // 等待后重试
}
}
}
return lastResult; // 最后一个任务的结果
}
async function run(gen) {
const iterator = gen();
async function step(nextFn, value) {
try {
const { value: yielded, done } = nextFn.call(iterator, value);
if (done) return yielded;
const resolved = yielded instanceof Promise ? await yielded : yielded;
return step(iterator.next, resolved);
} catch (err) {
return step(iterator.throw, err);
}
}
return step(iterator.next);
}
run(() => retryableTaskQueue(taskFns, 3, 1000))
.then(result => console.log("✅ 所有任务完成:", result))
.catch(err => console.error("❌ 有任务失败:", err.message));