Promise.all
Understanding Promise.all()
Like a Pro (Without Losing Your Mind)
If you’re diving into JavaScript, you’ve probably stumbled upon promises. Maybe you’ve already been traumatized by a few unhandled promise rejections. Don’t worry—we’ve all been there. Today, we’ll talk about a promise-related superhero: Promise.all()
.
Promise.all
is like a group project where everyone gets their part done at the same time (no free riders allowed!). But here’s the twist: if one person messes up, the whole project fails. So let’s explore this with two examples, one using the await
method and another with .then()
chaining.
What Does Promise.all
Do?
Promise.all
takes an array of promises and runs them concurrently. It waits until all promises resolve or rejects if any one of them fails.
It’s perfect for situations where you want multiple asynchronous tasks to finish before moving forward, like:
Fetching data for multiple countries.
Loading images for your meme website.
Ordering multiple pizzas at once (no waiting for that pineapple pizza 🍍 to arrive first).
NOTE: Promise.all()
waits for all promises in the array to either resolve or for one to reject. If any promise rejects, Promise.all()
immediately rejects: It short-circuits only when one of the promises rejects.
Example 1: Using Promise.all
with async/await
Let’s fetch data for three countries: Japan, Brazil, and Morocco.
const fetchCountries = async function () {
try {
const responses = await Promise.all([
fetch(`https://restcountries.com/v3.1/name/Japan`),
fetch(`https://restcountries.com/v3.1/name/Brazil`),
fetch(`https://restcountries.com/v3.1/name/Morocco`),
]);
const data = await Promise.all(responses.map((response) => response.json()));
console.log(data); // Logs data for Japan, Brazil, and Morocco
} catch (error) {
console.error("Uh-oh! Something went wrong:", error.message);
}
};
fetchCountries();
Breakdown
Promise.all
:Sends out three fetch requests at the same time.
Returns an array of
Response
objects when all requests resolve.
[Response, Response, Response]
.map
withresponse.json()
:Converts each
Response
into JSON.This returns another array of promises, which is why we need a second
Promise.all
to resolve them.
Example 2: Using Promise.all
with .then()
Chaining
Prefer chaining promises? No problem! Let’s write the same logic without async/await
.
Promise.all([
fetch(`https://restcountries.com/v3.1/name/Japan`),
fetch(`https://restcountries.com/v3.1/name/Brazil`),
fetch(`https://restcountries.com/v3.1/name/Morocco`),
])
.then((responses) => {
console.log('Responses:', responses); // Logs Response objects
return Promise.all(responses.map((response) => response.json()));
})
.then((data) => {
console.log('Countries Data:', data); // Logs JSON data
})
.catch((error) => {
console.error('Oops! Error fetching data:', error.message);
});
Breakdown
First
Promise.all
:Fetches data concurrently.
Returns an array of
Response
objects if all fetch requests succeed.
.map
+ SecondPromise.all
:Processes each
Response
to JSON.The second
Promise.all
ensures you get all the parsed data at once.
Why Use a Second Promise.all
?
The key here is understanding that response.json()
itself returns a Promise. Let’s break this down step by step:
Step 1: What Does fetch
Return?
fetch
gives you aPromise
that resolves to aResponse
object.The
Response
object has a.json()
method, but calling it doesn’t give you data right away. It gives you another Promise!
Step 2: First Promise.all
Resolves to Response Objects
When you use Promise.all
with multiple fetch
calls:
Promise.all([
fetch(`https://restcountries.com/v3.1/name/Japan`),
fetch(`https://restcountries.com/v3.1/name/Brazil`),
fetch(`https://restcountries.com/v3.1/name/Morocco`),
])
This resolves to an array of Response
objects:
[Response, Response, Response]
Step 3: .json()
Creates More Promises
When you do this:
responses.map((response) => response.json());
You get an array of Promises for JSON data:
[Promise, Promise, Promise]
Step 4: Enter the Second Promise.all
You need to wait for all these JSON Promises to resolve. That’s why you use a second Promise.all
:
Promise.all(responses.map((response) => response.json()));
What Happens Without the Second Promise.all
?
If you skip the second Promise.all
:
responses.map((response) => response.json());
You’ll end up with an array of Promises that haven’t resolved yet. Trying to access data here would be like biting into an unripe fruit—not ready yet! 🍏
Key Takeaways
Promise.all
is your friend when working with multiple asynchronous tasks.You might need a second
Promise.all
when dealing with promises within promises, likeresponse.json()
.Always handle errors with
.catch
ortry...catch
. You don’t want your app crashing because of one bad fetch.
Fun Fact
JavaScript doesn’t do anything half-heartedly. If you hand it a promise, it makes sure to follow through—just like how your dog will never leave a ball unchewed. 🐶
Now go forth and conquer those promises like the JavaScript wizard you are! 🧙♂️✨
Subscribe to my newsletter
Read articles from Hassani directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Hassani
Hassani
Hi 👋 I'm a developer with experience in building websites with beautiful designs and user friendly interfaces. I'm experienced in front-end development using languages such as Html5, Css3, TailwindCss, Javascript, Typescript, react.js & redux and NextJs 🚀