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

使用fetch获取ndjson流时如何构建包含所有单行数据的父对象

方案1:不修改现有readStream实现,直接在调用侧收集数据

直接在点击事件逻辑里新增一个数组存储每一行返回的对象即可,修改后的调用代码如下:

onClick={() => {
  // 声明空数组存储所有返回的单条数据
  const allGameList = [];
  // 你需要的父对象,可自定义结构挂载全量数据
  const resultParent = {
    total: 0,
    data: allGameList
  };

  const stream = fetch(
    'https://lichess.org/api/games/user/neio',
    { headers: { Accept: 'application/x-ndjson' } }
  );

  const onMessage = obj => {
    console.log('test', obj);
    // 每收到一条数据就塞入数组
    allGameList.push(obj);
  };

  const onComplete = () => {
    console.log('The stream has completed');
    // 流处理完成时,allGameList已经包含接口返回的所有单条数据
    resultParent.total = allGameList.length;
    console.log('全量父对象数据:', resultParent);
    // 后续对全量数据的操作都可以在这里执行
  };

  stream.then(readStream(onMessage)).then(onComplete);
}}

方案2:封装返回全量数据的工具函数(更符合Promise使用习惯)

如果不想每次都手动维护外部变量,可以重新封装流式读取工具,直接返回全量数据的Promise,使用更简洁:

封装工具函数

export const readStreamAll = response => {
  const stream = response.body.getReader();
  const matcher = /\r?\n/;
  const decoder = new TextDecoder();
  let buf = '';
  // 工具内部维护结果数组
  const resultList = [];

  const loop = () =>
    stream.read().then(({ done, value }) => {
      if (done) {
        if (buf.length > 0) {
          try {
            resultList.push(JSON.parse(buf));
          } catch (e) {
            console.error('单行数据解析失败', e);
          }
        }
        // 流完成时直接返回全量数据
        return resultList;
      } else {
        const chunk = decoder.decode(value, {
          stream: true,
        });
        buf += chunk;

        const parts = buf.split(matcher);
        buf = parts.pop();
        for (const i of parts) {
          try {
            resultList.push(JSON.parse(i));
          } catch (e) {
            console.error('单行数据解析失败', e);
          }
        }
        return loop();
      }
    });

  return loop();
};

调用方式

onClick={async () => {
  try {
    const response = await fetch(
      'https://lichess.org/api/games/user/neio',
      { headers: { Accept: 'application/x-ndjson' } }
    );
    // 直接await获取所有数据
    const allGameList = await readStreamAll(response);
    // 构造父对象
    const resultParent = {
      total: allGameList.length,
      data: allGameList
    };
    console.log('全量父对象数据:', resultParent);
  } catch (err) {
    console.error('请求或解析失败', err);
  }
}}

补充说明

  • 如果单条数据有唯一标识,你也可以把全量数据存为对象而非数组,用唯一ID作为key,方便后续查找
  • 代码中新增的try/catch用于捕获单行解析错误,避免某一行格式异常导致整个流处理终止

内容的提问来源于stack exchange,提问作者Jon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 05:09:02