Generator 配合 async/await 可实现按需加载的异步分页迭代器:每次 next() 触发下一页请求,保持游标状态;通过 yield 调度信号、async 函数驱动 fetch,支持 for await…of 消费,并可增强取消、重试与缓存能力。

Generator 可以配合 async/await 实现按需加载的异步分页迭代器,核心在于:每次调用 next() 时才触发下一页请求,且保持状态(如页码、游标或是否结束),避免一次性拉取全部数据。
基础思路:用 Generator 封装分页逻辑
Generator 函数本身不能直接 await,但可以 yield 一个 Promise,由外部消费方(如 for await...of)处理异步结果。更实用的方式是让 Generator 返回普通对象(含 value 和 done),而把异步请求逻辑交给内部函数,再用 async 函数包装 Generator 的遍历过程。
推荐组合方式:Generator 提供迭代协议 + 异步函数驱动分页请求。
实现一个支持游标分页的异步迭代器
假设后端接口为 GET /api/items?cursor=xxx,返回 { data: [...], next_cursor: "abc123" }:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
立即学习“Java免费学习笔记(深入)”;
function* createPageIterator(initialCursor = null) {
let cursor = initialCursor;
while (cursor !== undefined) {
yield { cursor }; // 告诉消费者“下一步该用这个 cursor 请求”
// 注意:这里不发请求,只产出调度信号
cursor = cursor === null ? 'start' : cursor; // 简单初始化
}
}
<p>// 外部用 async 函数驱动它,真正发起请求
async function* fetchPages(url, options = {}) {
let cursor = null;
for (const { cursor: nextCursor } of createPageIterator(cursor)) {
const params = new URLSearchParams({ cursor: nextCursor || '' });
const res = await fetch(<code>${url}?${params}</code>);
const { data, next_cursor } = await res.json();</p><pre class="brush:php;toolbar:false;">if (data.length === 0) break;
yield { items: data, hasNext: !!next_cursor };
cursor = next_cursor;} }
在业务中使用:for await…of 按需消费
这样就能自然地逐页加载、逐页处理,不提前请求后续页:
async function renderFeed() {
for await (const { items, hasNext } of fetchPages('/api/posts')) {
renderItems(items);
if (!hasNext) break;
// 可选:滚动到底自动加载下一页,或等用户点击
}
}
<p>// 或手动控制(比如点击“加载更多”)
const iterator = fetchPages('/api/comments');
async function loadNext() {
const { value, done } = await iterator.next();
if (!done && value?.items) {
appendComments(value.items);
}
}进阶:支持中断、重试与取消
实际项目中可增强健壮性:
- 用
AbortController支持取消当前请求(尤其用户快速翻页时) - 对
fetch加重试逻辑(封装成retryFetch) - 在 Generator 内部缓存已加载页,避免重复请求(适合“回退加载”场景)
- 结合
Symbol.asyncIterator让自定义类直接支持for await(需返回asyncIterator方法)

















