How to use Promise.all() in 5 minutes
What is Promise.all?
You might be wondering — what is Promise.all
? Promise.all is a method available on the Promise object that fulfills (i.e. becomes completed) when all of the promises that were passed into it have been completed.
The way you'll typically pass promises into the Promise.all
method is through a list of promises that you've made.
That's the part that is probably the most tedious — creating that list of promises that get passed into Promise.all
, but after that, it's smooth sailing!
You can follow along with this code here Promise All — StackBlitz.
And we'll be using this Programming Quotes API.
Our code will result in something like this
When to Use Promise.all
Use Promise.all
when...
You have repeated pieces of code that take a long time to complete (think seconds)
These slow-running pieces of code would benefit from running at the same time rather than one after the other
Why these suggestions?
Imagine you're making a request to an API to retrieve a programming quote to display in your app.
Let's say each request to that API takes 1 second to complete and you want 10 programming quotes.
If you perform each request to get the programming quote one after the other — the total time it'll take to do that will be at least 10 seconds.
Can you image the user experience as a result of that 10 second delay? It would be unusable!
Using Promise.all will speed things right up for us.
Setting up the Application component
Here's what that example would look like. You can add this in index.js
inside of the Application component.
Setup our state variables and the programming quote URL
const [timing1, setTiming1] = useState(null);
const [timing2, setTiming2] = useState(null);
const programQuoteUrl =
"https://programming-quotes-api.herokuapp.com/quotes/random";
And add our function that fetches the 10 programming quotes without using Promise.all
.
/** Here each of the quotes is fetched 1 after the other */
const fetchingWithoutPromiseAll = async () => {
const programmingQuote1 = await fetch(programQuoteUrl);
const programmingQuote2 = await fetch(programQuoteUrl);
const programmingQuote3 = await fetch(programQuoteUrl);
const programmingQuote4 = await fetch(programQuoteUrl);
const programmingQuote5 = await fetch(programQuoteUrl);
const programmingQuote6 = await fetch(programQuoteUrl);
const programmingQuote7 = await fetch(programQuoteUrl);
const programmingQuote8 = await fetch(programQuoteUrl);
const programmingQuote9 = await fetch(programQuoteUrl);
const programmingQuote10 = await fetch(programQuoteUrl);
};
Using Promise.all
From our scenario, we know that it'll take at least 10 seconds to get all 10 programming quotes.
How about — instead of requesting the programming quotes one after the other — we request them all at the same time using Promise.all
?
We would create our requests (meaning no await
in front of the fetch) and then store them in a list.
Add this into the Application component.
const fetchingWithPromiseAll = async () => {
// Set up the requests for the programming quotes
const programmingQuote1 = fetch(programQuoteUrl);
const programmingQuote2 = fetch(programQuoteUrl);
const programmingQuote3 = fetch(programQuoteUrl);
const programmingQuote4 = fetch(programQuoteUrl);
const programmingQuote5 = fetch(programQuoteUrl);
const programmingQuote6 = fetch(programQuoteUrl);
const programmingQuote7 = fetch(programQuoteUrl);
const programmingQuote8 = fetch(programQuoteUrl);
const programmingQuote9 = fetch(programQuoteUrl);
const programmingQuote10 = fetch(programQuoteUrl);
// Store them in a list
const listOfRequests = [
programmingQuote1,
programmingQuote2,
programmingQuote3,
programmingQuote4,
programmingQuote5,
programmingQuote6,
programmingQuote7,
programmingQuote8,
programmingQuote9,
programmingQuote10
];
// Fetches all quotes at the same time
const quotes = await Promise.all(listOfRequests);
// Your responses will be returned in a list
// in the same order as the list of requests
quotes.forEach(async (quote) => {
console.log(await quote.json());
});
};
And in that last line of code, we use Promise.all
by passing in the list of our requests.
The request for all 10 of the quotes will probably complete in 1-2 seconds.
Even though each individual request takes 1 second, the requests complete so fast because we're performing them at the same time instead of one after the other.
Your 10 programming quotes will be returned in a list and you can access them there to do whatever you'd like.
The user experience in this case would be phenomenal, and it's all thanks to Promise.all
!
Measure the Timing of Promise.all
If you'd like to see how much faster Promise.all
is, add the below to the bottom Application component.
This bit of code just tells those functions from earlier to fetch our programming quotes and measures the time each function took. a
useEffect(() => {
const performTimings = async () => {
// Time the fetches without Promise.all
const startTime1 = Date.now();
await fetchingWithoutPromiseAll();
const endTime1 = Date.now();
// Get the total time in seconds
const totalTime1 = (endTime1 - startTime1) / 1000;
// Time the fetches with Promise.all
const startTime2 = Date.now();
await fetchingWithPromiseAll();
const endTime2 = Date.now();
// Get the total time in seconds
const totalTime2 = (endTime2 - startTime2) / 1000;
setTiming1(totalTime1);
setTiming2(totalTime2);
};
// Execute the timing
performTimings();
}, []);
And here we'll add the code for displaying the timings.
if (timing1 && timing2) {
return (
<div>
<p>Total time it took to fetch 10 programming quotes without Promise.all: <strong>{timing1} seconds</strong></p>
<p>Total time it took to fetch 10 programming quotes with Promise.all: <strong>{timing2} seconds</strong></p>
</div>
)
} else {
return "Performing timings";
}
And there you have it — a complete understanding of when to use Promise.all
, how to use it, and the benefits it gives you.
The complete code is available here Promise All — StackBlitz in the branch titled "complete".