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 … drumroll … Promise.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.
Photo by Jake Blucker on Unsplash
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.