【问题标题】:Fail to parse on a json stream using node-fetch无法使用 node-fetch 解析 json 流
【发布时间】:2021-10-12 18:40:54
【问题描述】:

我从node-fetch 流功能运行示例代码。 有时它可以成功解析块,有时返回错误消息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()

有人知道为什么吗?我可以依赖块吗?

【问题讨论】:

    标签: node.js stream node-fetch jsonstream


    【解决方案1】:

    通过请求https://httpbin.org/stream/3,服务器通过流将数据分成3个块发送。客户端(在这种情况下是您的节点脚本)与服务器保持连接并不断接收数据并将它们拆分成块。

    node-fetch 只是在每次完成单个异步任务时将数据拆分为块,您可以在此处看到:line 199 of body.js。

    因此,如果拆分的数据到达如此之快,以至于异步任务在单个节点的事件循环中接收到多个数据块,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();
    

    【讨论】:

      猜你喜欢
      • 2021-06-02
      • 1970-01-01
      • 1970-01-01
      • 2020-03-31
      • 1970-01-01
      • 1970-01-01
      • 2015-12-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多