示例说明
把全量数据拉到本地再处理,内存和网络都会被一次性压满。异步生成器把数据流变成按需拉取的迭代协议:每 yield 一批就暂停,消费者处理完再要下一批;flatten 进一步把批降级成逐条流。break 提前退出时,生成器的 finally 语义会正确收尾,未拉取的页面根本不会被请求。
技术要点
- yield 暂停点让拉取节奏由消费侧决定
- 生成器组合保留批与条两级视角
- 提前 break 自动终止后续页面请求
代码解读
paginate 循环请求直到返回空批即终止;remote 是数据源适配器,把 offset 与 limit 翻译成查询参数。flatten 嵌套 for await 把每批行依次 yield。消费循环累计金额超过一万即 break,此时远端的剩余分页请求被生成器终止机制取消。
使用建议
生成器内部不要吞异常,让错误自然传播给消费者处理。数据源不稳定时可包一层重试生成器。条与批的选择取决于下游批量接口的形态。
代码示例
async function* paginate(source, pageSize = 100) {
let offset = 0;
while (true) {
const rows = await source(offset, pageSize);
if (rows.length === 0) return;
yield rows;
offset += rows.length;
}
}
async function* flatten(batches) {
for await (const batch of batches) {
for (const row of batch) {
yield row;
}
}
}
const remote = async (offset, limit) => {
const res = await fetch(
'https://api.example.com/records?offset=' + offset + '&limit=' + limit,
);
const body = await res.json();
return body.rows;
};
let total = 0;
for await (const row of flatten(paginate(remote))) {
total += row.amount;
if (total > 10_000) break; // 消费者随时可提前退出
}
console.log('accumulated amount:', total);