When you have several independent async tasks, run them at the same time and wait for all of them. Two methods do that.
Promise.all: all must succeed
Promise.all(array) returns a promise that resolves with an array of results (in the same order as the input), once every promise succeeds. If any rejects, it rejects immediately with that error (“fail fast”).
const wait = (ms, value) => new Promise(resolve => setTimeout(() => resolve(value), ms));
async function main() {
const [user, posts, settings] = await Promise.all([
wait(300, { name: "Maya" }),
wait(200, ["Post A", "Post B"]),
wait(100, { theme: "dark" })
]);
console.log(user.name, posts.length, settings.theme); // → Maya 2 dark
}
main();
The total time is about 300 ms (the slowest), not 600 ms (the sum). That is the whole point.
When one fails
const wait = (ms, value) => new Promise(resolve => setTimeout(() => resolve(value), ms));
const fail = ms => new Promise((_, reject) => setTimeout(() => reject(new Error("Request failed")), ms));
Promise.all([wait(100, "ok"), fail(50), wait(200, "ok")])
.then(results => console.log("results", results))
.catch(error => console.log("Promise.all failed:", error.message)); // → Promise.all failed: Request failed
You lose the results of the tasks that did succeed. Sometimes that is exactly right (a page needs all its data). Sometimes it is not.
Promise.allSettled: wait for all, never reject
Promise.allSettled waits for every promise to finish and gives you an array describing each outcome.
const wait = (ms, value) => new Promise(resolve => setTimeout(() => resolve(value), ms));
const fail = ms => new Promise((_, reject) => setTimeout(() => reject(new Error("Request failed")), ms));
Promise.allSettled([wait(100, "A"), fail(50), wait(150, "C")]).then(results => {
for (const result of results) {
if (result.status === "fulfilled") {
console.log("ok:", result.value);
} else {
console.log("failed:", result.reason.message);
}
}
});
Each result is { status: "fulfilled", value } or { status: "rejected", reason }. Use it for independent tasks where a partial result is still useful, like loading several dashboard widgets.
Which one?
| Situation | Use |
|---|---|
| All results are needed, fail if any fails | Promise.all |
| Show whatever worked, handle failures one by one | Promise.allSettled |
Non-promise values are fine
Promise.all([1, Promise.resolve(2), 3]).then(values => console.log(values)); // → [1, 2, 3]
An empty array
Promise.all([]) resolves immediately with [].