簡體   English   中英

無法使用 node-fetch 在 json stream 上解析

[英]Fail to parse on a json stream using node-fetch

我從node-fetch stream 功能運行示例代碼。 有時它可以成功解析塊,有時返回錯誤消息SyntaxError: Unexpected token { in JSON at position 312

const fetch = require('node-fetch');

async function main() {
  const response = await fetch('https://httpbin.org/stream/3');
  try {
    for await (const chunk of response.body) {
      console.log(JSON.parse(chunk.toString()));
    }
  } catch (err) {
    console.error(err.stack);
  }
}

main()

有人知道為什么嗎? 我可以依靠大塊嗎?

通過請求https://httpbin.org/stream/3 ,服務器通過 stream 發送分成 3 個塊的數據。客戶端(在本例中是您的節點腳本)保持與服務器的連接並繼續接收數據並將它們分成塊。

每次完成單個異步任務時, node-fetch只是將數據分成塊,如您在此處所見: body.js 的第 199 行

因此,如果拆分后的數據到達速度如此之快,以至於異步任務在單個節點的事件循環中接收到多個數據塊, node-fetch接收到多個 jason 數據。

那是錯誤發生的時候。 在添加了console.log的情況下運行以下代碼。 然后你可以確認當錯誤發生時,多個 jason 對象被保存在一個chunk中。

const fetch = require('node-fetch');

async function main () {
  const response = await fetch('https://httpbin.org/stream/3');
  try {
    for await (const chunk of response.body) {
      console.log("------chunk-----\n", chunk.toString());
      console.log("Char at 310 -- 315", chunk.toString().substring(310, 315));
      console.log(JSON.parse(chunk.toString()));
    }
  } catch (err) {
    console.error(err.stack);
  }
}

main()

對於本站,報錯時可以自行拆分數據如下。

const fetch = require('node-fetch');

async function main () {
  const response = await fetch('https://httpbin.org/stream/3');
  try {
    for await (const chunk of response.body) {
      try {
        console.log(JSON.parse(chunk.toString()));
      } catch (_) {
        console.log("------ Handling multiple chunks ------");
        chunk.toString().split("\n").slice(0, -1).forEach(d => console.log(JSON.parse(d)));
      }
    }
  } catch (err) {
    console.error(err.stack);
  }
}
main()

當您在瀏覽器中使用 Fetch API 時,您實際上可以編寫自己的ReadableStreamReader並實現如何處理拆分數據的策略。

更新:

您可以簡單地使用stream-json庫的jsonl Parser ,如下所示:

const { parser: jsonlParser } = require('stream-json/jsonl/Parser');

async function main () {
  const response = await fetch('https://httpbin.org/stream/5');
  response.body.pipe(jsonlParser())
    .on('data', ({ key, value }) => console.log(value))
    .on('end', () => console.log("Parsing done."))
    .on('error', err => console.log(err.message));
}

main();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM