【问题标题】:Reread a response body from JavaScript's fetch从 JavaScript 的 fetch 中重新读取响应正文
【发布时间】:2017-03-22 17:24:49
【问题描述】:

fetch() 返回承诺(如果成功)解析为 Response 对象。一个很常见的做法是立即调用 Response.json() 将响应正文转换为 JSON 对象。

如果响应正文不是有效的 JSON,则 Response.json() 承诺会失败并出现错误。消息大致如下:

JSON 中位置 0 处的意外标记 X

这在尝试诊断问题时不是很有帮助;理想情况下,我希望能够看到来自服务器的内容(这通常是一条错误消息)。

但是,您似乎只能在Response.body 读取流一次(至少在 Chrome 中)。 (甚至还有一个只读的 Response.bodyUsed 标志。)Response.json() 尝试将正文转换为 JSON 时已经发生了这种情况,因此如果 JSON 解析失败,正文似乎会永远丢失。

有没有办法恢复原始响应正文...当原始fetch Promise 解析时,除了手动读取它(然后转换为 JSON)之外?

【问题讨论】:

  • 您可以调用 response.text() 来读取返回的数据,即使它不是有效的 JSON,也可以克隆响应,但理想情况下,您的服务器应该始终在以下情况下返回 JSON你期望 JSON,即使是错误也应该返回为 JSON。

标签: javascript json stream fetch httpresponse


【解决方案1】:

我使用了JSON.parse(response.resp.data),因为不知何故克隆不起作用。

【讨论】:

    【解决方案2】:

    将 response.json() 分配给一个变量并返回它对我有用。 clone() 再次说它已锁定。

    fetch("http://localhost:3000/watchlist")
        .then(response => {
          var res = response.json();
          return res;
        })
        .then(data => {
          console.log(data);
          this.setState({ data });
        });
    

    【讨论】:

      【解决方案3】:

      我不得不处理一个偶尔会搞砸 JSON 响应的 API - 在返回 response.json() 之前,我克隆了响应对象。使用 catch 块,我可以确定错误是否是 SyntaxError,然后使用响应克隆的文本结果继续修复错误

      有点像这样:

      var brokenJson = function (url) {
          var responseCopy;
          return fetch(url)
          .then(function (response) {
              responseCopy = response.clone();
              return response.json();
          }).catch(function (err) {
              if (err instanceof SyntaxError) {
                  return responseCopy.text()
                  .then(function(data) {
                      return fixJson(data);
                  });
              }
              else {
                  throw err;
              }
          }).then(function (json) {
              // do things
          });
      };
      

      fixJson 只是一个修复接收到的数据的函数——在我的例子中,当它被 JSON 破坏时,它总是以同样的方式被破坏——我认为它有一个额外的前导 { 或尾随 }——不记得了

      重新阅读问题,您更有可能希望将错误记录到控制台而不是修复 json - 轻松重写:

      var brokenJson = function (url) {
          var responseCopy;
          return fetch(url)
          .then(function (response) {
              responseCopy = response.clone();
              return response.json();
          }).catch(function (err) {
              if (err instanceof SyntaxError) {
                  return responseCopy.text()
                  .then(function(text) {
                      console.error(text);
                      throw err;
                  });
              }
              else {
                  throw err;
              }
          }).then(function (json) {
              // do things
          });
      };
      

      【讨论】:

        【解决方案4】:

        使用Response.clone() 克隆Response

        let clone = response.clone();
        

        或者,使用返回ReadableStreamResponse.body.getReader()Response 读取为流,使用TextDecoder()Uint8Array 数据流转换为文本。

        【讨论】:

        猜你喜欢
        • 2021-05-14
        • 2017-01-04
        • 1970-01-01
        • 1970-01-01
        • 2017-12-18
        • 2012-08-14
        • 2017-03-17
        • 2022-11-04
        • 2022-01-22
        相关资源
        最近更新 更多