TypeScript中如何定义实现Async Iterator的类(Symbol.asyncIterator)
TypeScript 异步迭代器类实现方法
[Symbol.asyncIterator]() 是异步迭代协议的入口方法,核心要求是返回一个带next()方法的对象,next()方法必须返回Promise,最终解析为{ value: 迭代值, done: 迭代是否终止 }结构的结果。
针对MyAutoPager自动分页的场景,方法内部需要维护分页状态、处理分页请求、判断迭代终止条件,完整可运行的实现如下:
核心实现逻辑
- 迭代启动时重置分页状态(当前页码、是否加载完成标记),支持多次重复迭代
next()方法内先判断是否已加载完全部分页,是则直接返回终止标识- 未加载完成时发起对应页码的接口请求,拿到数据后更新分页状态,返回当前页数据
- 可选实现
return()方法,处理for await循环中途break/throw退出时的资源清理逻辑(比如取消未完成的请求)
完整TypeScript代码
// 分页接口返回结构,可根据你的业务实际调整 type PageResp<T> = { data: T[]; hasNextPage: boolean; } class MyAutoPager<T> { // 分页状态 private currentPageNum = 1; private readonly pageSize = 20; private isLoadDone = false; // 替换为你实际的分页请求逻辑 private async requestPage(page: number, size: number): Promise<PageResp<T>> { const resp = await fetch(`/your/list/api?page=${page}&size=${size}`); if (!resp.ok) throw new Error(`分页请求失败,状态码:${resp.status}`); return resp.json(); } [Symbol.asyncIterator]() { // 每次启动迭代时重置状态,避免上次迭代的状态干扰 this.currentPageNum = 1; this.isLoadDone = false; const ctx = this; return { async next(): Promise<IteratorResult<T[]>> { // 所有分页加载完成,终止迭代 if (ctx.isLoadDone) { return { done: true, value: undefined }; } // 请求当前页数据 const pageData = await ctx.requestPage(ctx.currentPageNum, ctx.pageSize); // 更新分页状态 ctx.currentPageNum += 1; ctx.isLoadDone = !pageData.hasNextPage; // 返回当前页数据,继续迭代 return { done: false, value: pageData.data }; }, // 可选:迭代中途退出时的清理逻辑 async return(): Promise<IteratorResult<T[]>> { ctx.isLoadDone = true; // 此处可添加取消未完成请求、清理临时缓存等逻辑 return { done: true, value: undefined }; } }; } }
使用方式
直接通过for await...of语法遍历即可,会自动按顺序拉取每一页数据:
const pager = new MyAutoPager<{ id: number; title: string }>(); // 遍历所有分页 for await (const currentPageList of pager) { console.log('当前页数据:', currentPageList); // 不需要继续遍历可直接break,会触发return方法执行清理 if (currentPageList.some(item => item.id === 0)) break; }
注意事项
- 如果需要在请求失败时终止迭代,可在
next()方法内加try/catch捕获请求异常,捕获后返回{ done: true, value: undefined }即可;如果需要外层感知错误,直接抛出异常即可 - 不要把分页状态定义在返回的迭代器对象外部的共享位置,避免多个迭代实例同时遍历的时候状态互相干扰
- 若不需要支持多次重复迭代,也可以直接在类上实现
next()方法,让类实例本身就是迭代器对象,但这种写法多次遍历会从上一次结束的位置继续,不符合分页场景的常规预期。
内容的提问来源于stack exchange,提问作者rattray
相关产品推荐
相关产品推荐

