Handling Multiple Awaits
Open the project folder
In our starter files, open the index.html page from this lessons folder:
10.Async-JavaScript > 07.Handling-multiple-awaits
Starter file code
Previously, we discussed the effects of multiple await calls, and here we have three in the starter project:
const response = await fetch('https://dog.ceo/api/breeds/image/random');
const response2 = await fetch('https://dog.ceo/api/breeds/image/random');
const response3 = await fetch('https://dog.ceo/api/breeds/image/random');
This is fine if the second one relies on data from the first for example. If not, we should not block the code unnecessarily.
With multiple requests for async data like this, this brings us back to earlier where we looked at how to handle multiple promises.
How do we know if one fails, or if they all fail? How could we handle this? With promises we could use methods such as all() and allSettled().
The Promise.all method
With async / await, these are promises behind the scenes. Meaning we can still use these methods, such as the all method:
async function setImage() {
  const response = await fetch('https://dog.ceo/api/breeds/image/random');
  const response2 = await fetch('https://dog.ceo/api/breeds/image/random');
  const response3 = await fetch('https://dog.ceo/api/breeds/image/random');
  // add Promise.all and console log:
  const result =  Promise.all([response, response2, response3]);
  console.log(result);
}
setImage();
A pending Promise is the result in the console:
Promise {<pending>}
Remember, the all method will resolve into one Promise if all of the promises it takes in resolve successfully, or if a single one fails. We can also use await to make sure they all resolve first before moving onto the console.log line:
// add await
const result = await Promise.all([response, response2]);
Since we are now waiting on the all method, we do not need to await on the three fetch promises individually, so we can remove the await keyword from each:
async function setImage() {
  const response = fetch("https://dog.ceo/api/breeds/image/random");
  const response2 = fetch("https://dog.ceo/api/breeds/image/random");
  const response3 = fetch("https://dog.ceo/api/breeds/image/random");
  // ...
}
The console will now show three responses:
Response {type: "cors", url: "https://dog.ceo/api/breeds/image/random", redirected: false, status: 200, ok: true, …}
Response {type: "cors", url: "https://dog.ceo/api/breeds/image/random", redirected: false, status: 200, ok: true, …}
Response {type: "cors", url: "https://dog.ceo/api/breeds/image/random", redirected: false, status: 200, ok: true, …}
Expand one of these objects:
body: (...)
bodyUsed: false
headers: Headers {}
ok: true
redirected: false
status: 200
statusText: ""
type: "cors"
url: "https://dog.ceo/api/breeds/image/random"
And we see we don’t have the data we need. Like earlier, the url value is the one we used to make the request.
Reading the body content with json()
To access the correct url, we need to extract the random image data from the body. And we do this with the json() method.
Remember this json method will read the contents of the response body and turn it into a readable JavaScript object.
Here we have an array with three values, we can loop over the array and apply the json method to each one:
async function setImage() {
  const response = fetch('https://dog.ceo/api/breeds/image/random');
  const response2 = fetch('https://dog.ceo/api/breeds/image/random');
  const response3 = fetch('https://dog.ceo/api/breeds/image/random');
  const result = await Promise.all([response, response2, response3]);
  result.forEach(function (value) {
    console.log(value.json());
  });
}
Console:
Promise {<pending>}
Promise {<pending>}
Promise {<pending>}
We see three promises instead of the random image data. This happens because the json method also returns a promise, so we need to await it:
result.forEach(function (value) {
  console.log(await value.json());
});
And await needs to be used inside of an async function or we will get an error:
result.forEach(async function (value) {
  console.log(await value.json());
});
Leaving us with the random image data in the console:
{message: 'https://images.dog.ceo/breeds/brabancon/n02112706_835.jpg', status: 'success'}
{message: 'https://images.dog.ceo/breeds/affenpinscher/n02110627_11942.jpg', status: 'success'}
{message: 'https://images.dog.ceo/breeds/airedale/n02096051_2265.jpg', status: 'success'}
This all method now means we can do something after all have been successful, or, we will know if one of them fails.