Generator 通过惰性求值和按需生成支持流式处理与过滤,可链式组合 map/filter/take 等单一职责函数,并借助 async function 处理异步数据流,但需避免展开大数组、误用 yield 或重复遍历同一实例。

Generator 通过 惰性求值 和 按需生成 的特性,天然适合流式处理与过滤——它不一次性加载全部数据,而是在每次 next() 调用时产出一个值,配合 yield*、条件判断和组合函数,就能构建可复用、内存友好的数据处理管道。
用 yield 实现基础流式过滤
在 Generator 函数内部,遍历输入源(如数组、迭代器或异步数据流),对每个元素做判断,只对符合条件的调用 yield。这样输出的就是一个“过滤后的新迭代器”,消费时才真正执行判断逻辑。
例如:从无限自然数中取前 5 个偶数:
let i = 0;
while (true) yield i++;
}
function* evens(source) {
for (const n of source) {
if (n % 2 === 0) yield n;
}
}
const result = [...evens(naturals())].slice(0, 5); // [0, 2, 4, 6, 8]
链式组合多个处理步骤
每个 Generator 可专注单一职责(如 map、filter、take),通过嵌套调用实现管道式组合。注意:Generator 函数返回的是迭代器,不是值,所以要层层传递迭代器对象。
立即学习“Java免费学习笔记(深入)”;
-
map(gen, fn):对每个产出值应用转换函数 -
filter(gen, predicate):只 yield 满足条件的值 -
take(gen, n):最多 yield 前 n 个值,然后return - 组合写法:
take(filter(map(data, x => x * 2), x => x > 10), 3)
处理异步数据流(配合 async/await)
标准 Generator 不支持 await,但可用 async function*(Async Generator)处理异步源,比如逐页拉取 API 数据并实时过滤:
let page = 1;
while (true) {
const res = await fetch(`/api/users?page=${page}&size=${pageSize}`);
const users = await res.json();
if (users.length === 0) break;
for (const u of users) {
if (u.active) yield u; // 过滤活跃用户
}
page++;
}
}
// 消费前 10 个活跃用户
const activeUsers = [];
for await (const user of fetchUsers()) {
if (activeUsers.length >= 10) break;
activeUsers.push(user);
}
避免常见陷阱
- 不要在 Generator 内直接展开大数组(如
[...arr]),会失去惰性;应直接for...of arr -
yield*用于委托另一个可迭代对象,适合复用已有 Generator 或数组,但要注意它会完全展开被委托的迭代器 - 多次遍历同一个 Generator 实例会立即结束(因为状态已耗尽),需要重新调用函数获取新迭代器
- 调试时可用
Array.from(gen)或展开语法快速查看前几项,但生产环境慎用,尤其对无限或大数据源


















