← 中文资源

简体中文版本

异步生成器分批迭代

用异步生成器惰性拉取远端分页数据:每轮只取一批并在 yield 处暂停,消费者控制节奏、可随时提前退出,内存保持恒定。

阅读英文原文

示例说明

把全量数据拉到本地再处理,内存和网络都会被一次性压满。异步生成器把数据流变成按需拉取的迭代协议:每 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);