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
相关产品推荐
相关产品推荐

