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

Node环境下无法消费NDJSON流,但相同代码在React中可正常运行

解决Node环境下消费Lichess NDJSON流的问题

我来帮你理清这里的问题,以及给出可行的解决方案:

问题根源分析

1. node-fetch + can-ndjson-stream 报错的原因

can-ndjson-stream这个库是为浏览器环境设计的,它依赖浏览器原生的ReadableStream API。但在Node.js里,fetch返回的res.body是Node.js自己的Readable流(属于stream模块),和浏览器的ReadableStream完全不是一个东西,所以会抛出ReferenceError: ReadableStream is not defined的错误。

2. Axios挂起的原因

Axios默认会把整个响应内容加载到内存中(缓冲成字符串/Buffer),不会返回流式响应。所以你拿到的res.data已经是完整的响应内容,不是流,自然没法用流读取器处理,导致程序挂起。


解决方案

方案一:使用Node.js原生流 + ndjson库(推荐)

Node.js有自己成熟的流处理体系,配合专门为Node设计的ndjson包,是最稳妥的方式:

首先安装依赖:

npm install ndjson node-fetch

然后编写代码:

import fetch from "node-fetch";
import ndjson from "ndjson";

async function fetchLichessTVFeed() {
  const res = await fetch("https://lichess.org/api/tv/feed");
  
  if (!res.ok) {
    throw new Error(`HTTP error! status: ${res.status}`);
  }

  // 将Node.js的Readable流通过ndjson解析器转换
  res.body.pipe(ndjson.parse())
    .on("data", (data) => {
      console.log("收到数据:", data);
    })
    .on("error", (err) => {
      console.error("流处理错误:", err);
    })
    .on("end", () => {
      console.log("流结束");
    });
}

fetchLichessTVFeed().catch(console.error);

方案二:Polyfill浏览器ReadableStream,继续使用can-ndjson-stream

如果你坚持要用can-ndjson-stream,需要在Node环境中polyfill浏览器的ReadableStream,同时让node-fetch返回兼容的流:

首先安装依赖:

npm install can-ndjson-stream node-fetch web-streams-polyfill

然后编写代码:

// 先polyfill浏览器的ReadableStream
import { ReadableStream } from "web-streams-polyfill";
globalThis.ReadableStream = ReadableStream;

import ndjsonStream from "can-ndjson-stream";
import fetch from "node-fetch";

async function fetchLichessTVFeed() {
  const res = await fetch("https://lichess.org/api/tv/feed", {
    // 让node-fetch返回浏览器风格的ReadableStream
    duplex: "half"
  });

  if (!res.ok) {
    throw new Error(`HTTP error! status: ${res.status}`);
  }

  const stream = ndjsonStream(res.body);
  const reader = stream.getReader();

  async function readStream() {
    let result;
    do {
      result = await reader.read();
      if (result.value) {
        console.log("收到数据:", result.value);
      }
    } while (!result.done);
  }

  await readStream();
}

fetchLichessTVFeed().catch(console.error);

方案三:使用Axios的流式响应

Axios支持配置流式响应,需要设置responseType: 'stream',然后用Node的流处理:

首先安装依赖:

npm install axios ndjson

然后编写代码:

import axios from "axios";
import ndjson from "ndjson";

async function fetchLichessTVFeed() {
  const res = await axios.get("https://lichess.org/api/tv/feed", {
    responseType: "stream", // 关键配置:返回Node.js流
  });

  res.data.pipe(ndjson.parse())
    .on("data", (data) => {
      console.log("收到数据:", data);
    })
    .on("error", (err) => {
      console.error("流处理错误:", err);
    })
    .on("end", () => {
      console.log("流结束");
    });
}

fetchLichessTVFeed().catch(console.error);

这些方案都能在Node环境中正确消费Lichess的NDJSON流,推荐用方案一,因为它最贴合Node.js的生态,也最稳定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 17:13:11