You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 07:18:30