Sync up multiple Promises to a single result set with Promise.all

Did you ever try to use data from multiple Promises but could not figure out how to sync up the requests to return a single result or Promise?

For example: A http request (e.g. using fetch) returns a single Promise that is executed asynchronously. If you would just execute a bunch of requests, there is no chance to get all responses into one array just by calling them after each other.

That’s why we need to wait until all requests are finished, to gather the data they return. The secret sauce to conquer this problem is … drumrollPromise.all

Waiting for Promises to resolve with Promise.all

To visualize our problem, I created a minimum example.

We want to fetch data from multiple different pages and return a single array as a result set. Have a look at the code first and I’ll explain it step by step afterwards.

fetchData = () => {
  const urls = [
    "https://jsonplaceholder.typicode.com/posts/1",
    "https://jsonplaceholder.typicode.com/posts/2",
    "https://jsonplaceholder.typicode.com/posts/3",
    "https://jsonplaceholder.typicode.com/posts/4",
    "https://jsonplaceholder.typicode.com/posts/5",
    "https://jsonplaceholder.typicode.com/posts/6",
    "https://jsonplaceholder.typicode.com/posts/7",
    "https://jsonplaceholder.typicode.com/posts/8"
  ];

  const allRequests = urls.map(url => 
    fetch(url).then(response => response.json())
  );

  return Promise.all(allRequests);
};

In this example, we iterate through the different URLs and fire a HTTP request for each of them with fetch. But because fetch returns a Promise too, we have to retrieve and return the data from the response of our request. So response.json() does the job to transform the response data to a JSON object.

As soon as map has finished iterating through our url array, it returns an array of Promises that are asynchronously fetching data from our URLs.

Now here’s the key point: To wait until all Promises are finished, we have to wrap them into a Promise.all call. This will not only wait until all Promises are resolved, it will also return an Array of whatever your Promises return.

If you return Promise.all from a function, be aware that it returns a Promise. To get access to the data we returned in all those Promises, you would simply need to call .then() like here:

fetchData().then(arrayOfResponses => 
  console.log("The data we got from the server:", arrayOfResponses)
);

As our http requests return a single JSON object, arrayOfResponses will contain each of them bundled together in a single array.

Wrapping up

Congratulations! You now know the secret sauce to sync up multiple Promises to return a single array as a result set. But Promise.all is not only useful to concat the results of multiple HTTP requests! You can use it whenever you need to wait until all Promises resolved, or e.g. if you have to compose objects from data from different asynchronous endpoints.

If you want to know more about Promise.all, I recommend to read the MDN Documentation.

Improve your React Skills!

Learn about React concepts, helpful libraries or get tips & tricks for deploying your app and many more topics.

I semi regularly post about React. Don't miss out on my future posts! Sign up below to get them delivered directly into your inbox!

Photo by Jake Blucker on Unsplash

One thought on “Sync up multiple Promises to a single result set with Promise.all”

  1. hey.. i am using promise..but as i increase the no of fetch calls , my render gets called for each of those fetch requests. Also i’m trying to get the results in a single array.

    const urls =[
    http://localhost:3000/machines/${id},
    http://localhost:3000/os/${oid}
    ];
    Promise.all(
    urls.map(url =>
    fetch(url,{credentials:’include’})
    .then(res => res.json())
    .then(data => data.data)
    )
    ).then(data => {
    this.setState({
    todos: [].concat(…data)
    });
    });

    this is the code for my promise

    Thanks in advance.

Leave a Reply

Your email address will not be published. Required fields are marked *