15

I am trying to do a multiple parallel fetch requests in react-native. But i don't get the response data as expected. What am i integrating it wrongly?

async componentDidMount() {
    try {
        let [res1, res2] = await Promise.all([
            fetch(apiUrl1),
            fetch(apiUrl2),
        ]);

        console.warn(res1);
        console.warn(res2);
    }
    catch(err) {
        console.warn(err);
    };
}

THis is the weird response i got.

{"_bodyBlob": {"_data": {"__collector": [Object], "blobId": "4", "offset": 0, "size": 661}}, "_bodyInit": {"_data": {"__collector": [Object], "blobId": "", "offset": 0, "size": 661}}, "headers": {"map": {"cache-control": "no-store, no-cache, must-revalidate", "cf-cache-status": "DYNAMIC", "cf-ray": "5", "content-type": "application/json; charset=utf-8", "date": "Thu, 09 Jan 2020 12:15:40 GMT", "expect-ct": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"", "expires": "", "pragma": "no-cache", "server": "cloudflare", "set-cookie": "ci_session=; expires=; Max-Age=7200; path=/; HttpOnly"}}, "ok": true, "status": 200, "statusText": undefined, "type": "default", "url": "apiurl"}
vincentsty
  • 2,963
  • 7
  • 34
  • 51
  • Does this answer your question? [Call async/await functions in parallel](https://stackoverflow.com/questions/35612428/call-async-await-functions-in-parallel) – Ismael Padilla Jan 09 '20 at 12:29
  • @IsmaelPadilla unfortunately not. That is the exact same code i implemented as u have seen but it does not work for request using `fetch API`. It should have been the right way of using `Promise.All` for parallel request but the problem is how to make it work with `fetch API` – vincentsty Jan 09 '20 at 12:32

3 Answers3

22

I'm a bit late, but it seemed like a good idea to show you how to perform multiple requests and wait for their resolution using only Promise.all and async/await.

The code below also shows how to handle errors correctly for multiple HTTP requests. I mention this because due to the way fetch() works, the catch block of your code will not be executed when HTTP errors occur:

A fetch() promise only rejects when a network error is encountered (which is usually when there’s a permissions issue or similar). A fetch() promise does not reject on HTTP errors (404, etc.). Instead, a then() handler must check the Response.ok and/or Response.status properties. – Taken from MDN

(async () => {
  try {
    const urls = [
      "https://api.chucknorris.io/jokes/random",
      "https://api.chucknorris.io/jokes/random",
      "https://api.chucknorris.io/jokes/random",
      "https://api.chucknorris.io/jokes/random",
    ];

    const requests = urls.map((url) => fetch(url));
    const responses = await Promise.all(requests);
    const errors = responses.filter((response) => !response.ok);

    if (errors.length > 0) {
      throw errors.map((response) => Error(response.statusText));
    }

    const json = responses.map((response) => response.json());
    const data = await Promise.all(json);

    data.forEach((datum) => console.log(datum));
  }
  catch (errors) {
    errors.forEach((error) => console.error(error));
  }
})();

For clarity, I also leave you an equivalent method using then():

(() => {
  const urls = [
    "https://api.chucknorris.io/jokes/random",
    "https://api.chucknorris.io/jokes/random",
    "https://api.chucknorris.io/jokes/random",
    "https://api.chucknorris.io/jokes/random",
  ];
  const requests = urls.map((url) => fetch(url));

  Promise.all(requests)
    .then((responses) => {
      const errors = responses.filter((response) => !response.ok);

      if (errors.length > 0) {
        throw errors.map((response) => Error(response.statusText));
      }

      const json = responses.map((response) => response.json());
      return Promise.all(json);
    })
    .then((data) => {
      data.forEach((datum) => console.log(datum));
    })
    .catch((errors) => {
      errors.forEach((error) => console.error(error));
    });
})();
Pablo H.
  • 331
  • 2
  • 7
20

Use the below code if your response is coming in json

 let [res1, res2] = await Promise.all([
            fetch(apiUrl1).then(response => response.json()),
            fetch(apiUrl2).then(response => response.json()),
        ]);

Vipin Yadav
  • 947
  • 4
  • 13
5

The Promise.all() method returns a single Promise that fulfills when all of the promises passed as an iterable have been fulfilled or when the iterable contains no promises. It rejects with the reason of the first promise that rejects. - From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

What you just did there is assign a Promise resolve to a variable and then console.log it. Which is not what you want. Something like this should give the results you want?

async componentDidMount() {
    try {
        await Promise.all([
            fetch(apiUrl1),
            fetch(apiUrl2),
        ]).then([res1, res2] => {    
            console.warn(res1);
            console.warn(res2); 
        });
    }
    catch(err) {
        console.warn(err);
    };
}