【问题标题】:Can't call fetch api multiple times无法多次调用 fetch api
【发布时间】:2020-12-30 18:10:17
【问题描述】:

我想在我的项目中多次调用这个api,当我调用它时,它继续给出一个错误

TypeError:无法在“响应”上执行“json”:已经有正文流 阅读 main.js:Line number

我的代码如下

let thisIsUrl = 'https://api.covid19api.com/summary';
let a = fetch(thisIsUrl)
a.then((data) => {
    return data.json()
}).then((apidata) => {
    console.log(apidata)
    return apidata
}).catch((error) => {
    console.log(error)
})


a.then((fetchdata) => {
    return fetchdata.json()
}).then((readingData) => {
    console.log(readingData)
}).catch((err) => {
    console.log(err)
})

【问题讨论】:

  • fetch 的结果分配给变量有什么特别的原因吗?我的意思是你为什么不每次都使用一个新的fetch 实例? fetch(thisIsUrl).then((data)...?

标签: javascript promise fetch typeerror


【解决方案1】:

没有多次致电fetch。您将其称为 once,然后尝试多次读取响应正文。这就是为什么错误提示您在流已关闭时尝试读取正文 - 当您第一次完成读取时它已关闭。

如果您想使用两次数据,请将其存储在某个地方并使用两次。

let thisIsUrl = 'https://api.covid19api.com/summary';
let a = fetch(thisIsUrl)
a.then((data) => {
    return data.json()
}).then((apidata) => {
    // **************** Use it twice here
}).catch((error) => {
    console.log(error)
})

如果您想再次获取它,因为它可能已更新,请再次致电fetch

let thisIsUrl = 'https://api.covid19api.com/summary';
fetch(thisIsUrl)
.then((data) => {
    return data.json();
}).then((apidata) => {
    console.log(apidata);
    return apidata;
}).catch((error) => {
    console.log(error);
});


// Presumably this is later (in time), not immediately after the above
fetch(thisIsUrl)
.then((fetchdata) => {
    return fetchdata.json();
}).then((readingData) => {
    console.log(readingData);
}).catch((err) => {
    console.log(err);
});

最后,这似乎不太可能,但如果您真的想获取一次并通过承诺链在多个地方使用该结果,请保留来自then 的承诺,而不是来自fetch 的承诺:

let thisIsUrl = 'https://api.covid19api.com/summary';
let a = fetch(thisIsUrl)
.then((data) => {
    return data.json()
});
a.then((apidata) => {
    // ***** Use it here
}).catch((error) => {
    console.log(error)
})

a.then((readingData) => {
    // ***** And then again here
}).catch((err) => {
    console.log(err);
});

旁注:您的代码正在成为fetch API 中的猎物;我已经在this blog post 中写过它。 fetch 只拒绝它对 network 错误的承诺,而不是 HTTP 错误。您必须通过在响应对象上检查ok,在第一个履行处理程序中自己检查这些:

fetch("/your/resource")
.then(response => {
    if (!response.ok) {
        throw new Error("HTTP error " + response.status); // Or better, use an Error subclass
    }
    return response.json();
})
// ...

【讨论】:

    【解决方案2】:

    fetch 返回Promise,一般情况下,promise 内部有类似状态的东西;

    1. pending:初始状态,既不满足也不拒绝。
    2. fulfilled:表示操作成功完成。
    3. rejected:表示操作失败。

    (source)

    因此,当我们调用它们并使用 thencatch 等从它们那里获取值时,它们会在调用后更改状态。所以在这里,当你用 a.then(… 读取值时,promise 将其状态更改为 fulfilled 并且你不能再次调用它,你需要一个新的和新鲜的 Promise,实际上是 fetch 的一个新实例。

    【讨论】:

      【解决方案3】:

      我想推荐你使用 Promise.all()。

      let thisIsUrl = 'https://api.covid19api.com/summary';
      let a = fetch(thisIsUrl)
      .then((data) => {
          return data.json()
      }).then((apidata) => {
          console.log(apidata)
          return apidata
      }).catch((error) => {
          console.log(error)
      })
      
      Promise.all([a,a,a]);
      .then(results => {
           // Results are here.
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-10-24
        • 2021-01-12
        • 1970-01-01
        • 2023-01-23
        • 1970-01-01
        • 2021-09-03
        • 1970-01-01
        相关资源
        最近更新 更多