简体   繁体   中英

Can't call fetch api multiple times

I want to call this api multiple times in my project and when I am calling it, It continues giving an error which is

TypeError: Failed to execute 'json' on 'Response': body stream already read at main.js: Line number

My Code is as Follows

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)
})

You're not calling fetch multiple times. You're calling it once , and then trying to read the response body multiple times. That's why the error says you're trying to read the body when the stream is already closed — it was closed when you were done reading it the first time.

If you want to use the data twice, store it somewhere and use it twice.

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)
})

If you want to fetch it again because it may have been updated, call fetch again:

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);
});

Finally, this seems unlikely, but if you really want to fetch it once and use that one result in multiple places via the promise chain, keep the promise from then rather than the promise from 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);
});

Side note: Your code is falling prey to a footgun in the fetch API; I've written about it in this blog post . fetch only rejects its promise on network errors, not HTTP errors. You have to check for those yourself in the first fulfillment handler, by checking for ok on the response object:

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

fetch returns Promise , generally, promises have something like state inside themself;

  1. pending : initial state, neither fulfilled nor rejected.
  2. fulfilled : meaning that the operation was completed successfully.
  3. rejected : meaning that the operation failed.

( source )

So when we call them and get the value from them with then , catch and etc. then they change the state after that call. So here, when you read the value with a.then(… , the promise changes its state to fulfilled and you are not able to call it again, you need a new and fresh Promise, actually a new instance of the fetch .

I want to recommend you to use 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.
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM