Promise.all
This lesson explains Promise.all with clear examples, use cases, and best practices so you can use modern JavaScript confidently in real projects.
ES6+ Promise.all Overview
Promise.all() runs multiple Promises in parallel and
waits for all of them to fulfill. It returns a single Promise that
resolves with an array of results in the same order as the input.
This method is ideal when every async task must succeed before you
continue, such as loading all required data for a page, uploading
multiple files together, or fetching related resources at once.
| Feature | Description |
| Introduced In | ES6 (ECMAScript 2015) |
| Input | Iterable of Promises or values |
| Resolves When | All Promises fulfill |
| Rejects When | Any single Promise rejects |
| Result Order | Matches the input order |
| Common Uses | Parallel API calls, batch uploads, data aggregation |
Basic Promise.all Example
const p1 = Promise.resolve("User");
const p2 = Promise.resolve("Orders");
const p3 = Promise.resolve("Settings");
Promise.all([p1, p2, p3])
.then((results) => {
console.log(results);
})
.catch((error) => {
console.error(error);
});
When all three Promises fulfill,
Promise.all() resolves with
["User", "Orders", "Settings"].
How Promise.all Works
Promise.all() starts every Promise at the same time.
It does not wait for one to finish before starting the next.
| Step | Description | Example |
| Pass Iterable | Provide an array of Promises. | [p1, p2, p3] |
| Run in Parallel | All Promises start immediately. | Concurrent requests |
| Collect Results | Store fulfilled values in order. | [value1, value2] |
| Resolve Together | Return when all succeed. | results |
| Fail Fast | Reject immediately on first failure. | .catch(...) |
Parallel Fetch Requests
Promise.all([
fetch("/api/user"),
fetch("/api/orders"),
fetch("/api/settings")
])
.then((responses) =>
Promise.all(
responses.map((res) => res.json())
)
)
.then(([user, orders, settings]) => {
console.log(user);
console.log(orders);
console.log(settings);
})
.catch((error) => {
console.error(
"One request failed:",
error
);
});
This is one of the most common real-world uses of
Promise.all(). Multiple API calls run at the same time
instead of one after another.
Fail-Fast Error Handling
const tasks = [
Promise.resolve("Step 1 done"),
Promise.reject(
new Error("Step 2 failed")
),
Promise.resolve("Step 3 done")
];
Promise.all(tasks)
.then((results) => {
console.log(results);
})
.catch((error) => {
console.error(error.message);
});
If any Promise rejects, Promise.all() rejects
immediately with that error. The remaining successful results are
not returned.
Promise.all with Array.map
const userIds = [1, 2, 3, 4];
const requests = userIds.map((id) =>
fetch(
`https://jsonplaceholder.typicode.com/users/${id}`
).then((res) => res.json())
);
Promise.all(requests)
.then((users) => {
console.log(
users.map((user) => user.name)
);
})
.catch((error) => {
console.error(error);
});
Mapping over an array to create Promises and passing them to
Promise.all() is a clean pattern for batch requests.
Promise.all with async/await
async function loadDashboard() {
try {
const [userRes, statsRes] =
await Promise.all([
fetch("/api/user"),
fetch("/api/stats")
]);
const user =
await userRes.json();
const stats =
await statsRes.json();
return { user, stats };
} catch (error) {
console.error(
"Dashboard load failed",
error
);
throw error;
}
}
loadDashboard()
.then((data) => console.log(data));
async/await makes Promise.all() results
easy to destructure into named variables for cleaner application
code.
Non-Promise Values in Promise.all
Promise.all([
Promise.resolve("Async value"),
42,
"plain string"
])
.then((results) => {
console.log(results);
});
Non-Promise values are treated as already fulfilled. This means you
can mix Promises and plain values in the same array.
Empty Array Behavior
Promise.all([])
.then((results) => {
console.log(results);
console.log(results.length);
});
Passing an empty array to Promise.all() resolves
immediately with an empty array. This is useful for dynamic lists
that may sometimes contain zero tasks.
Sequential vs Parallel Execution
// Sequential: slower
async function loadSequential() {
const user =
await fetch("/api/user");
const orders =
await fetch("/api/orders");
return [user, orders];
}
// Parallel: faster
async function loadParallel() {
const [user, orders] =
await Promise.all([
fetch("/api/user"),
fetch("/api/orders")
]);
return [user, orders];
}
Use Promise.all() when tasks are independent and can
run at the same time. Use sequential await when one
task depends on the result of another.
Promise.all vs Other Combinators
| Method | Resolves When | Rejects When | Best For |
Promise.all() | All Promises fulfill | Any Promise rejects | All tasks must succeed |
Promise.allSettled() | All Promises settle | Never rejects | Partial success reporting |
Promise.race() | First Promise settles | First Promise rejects | First finished result |
Promise.any() | First Promise fulfills | All Promises reject | First successful result |
Common Promise.all Use Cases
- Loading multiple API endpoints for a single page.
- Uploading several files at the same time.
- Fetching user data from multiple microservices.
- Running independent validation checks in parallel.
- Preloading assets before rendering a view.
- Batch database or cache lookups.
- Waiting for all setup tasks before app initialization.
Promise.all Best Practices
- Use
Promise.all() only when every task must succeed. - Prefer parallel requests for independent async work.
- Always handle rejection with
.catch() or try/catch. - Destructure results with meaningful variable names.
- Use
Promise.allSettled() when partial failure is acceptable. - Avoid unnecessary Promise wrappers around synchronous values.
- Consider timeouts or retries for unreliable network requests.
Common Promise.all Mistakes
- Using
Promise.all() when only some results are required. - Assuming tasks run sequentially instead of in parallel.
- Forgetting that one failure rejects the entire batch.
- Not handling errors from any individual Promise.
- Using
Promise.all() for dependent sequential workflows. - Expecting result order to match completion time instead of input order.
- Passing an array of unresolved fetch calls without parsing responses.
Key Takeaways
Promise.all() runs multiple Promises in parallel. - It resolves with an array of results in input order.
- It rejects immediately if any Promise fails.
- It is best for workflows where every task must succeed.
- Pair it with
async/await for clean, readable code.
Pro Tip
If a page needs user, orders, and settings data and all three are
required to render, Promise.all() is the right choice.
If one section can fail independently, use
Promise.allSettled() instead.