JavaScript Promise utilities help you manage multiple asynchronous operations efficiently. Instead of waiting for promises one by one, you can use built-in methods to run multiple promises together and decide how to handle their results.
JavaScript provides four important Promise utilities:
Promise.all()Promise.allSettled()Promise.race()Promise.any()
Although these methods accept multiple promises, each one behaves differently when promises resolve or reject. Understanding these differences helps you write better asynchronous JavaScript code.
What Are JavaScript Promise Utilities?
Promise utilities are built-in JavaScript methods that work with multiple promises. They help you collect results, handle failures, or respond when a particular promise settles.
For example, a web application might need to:
- Fetch user details and order information.
- Wait for several API requests to finish.
- Use the fastest response from multiple servers.
- Accept the first successful result from multiple services.
You can manage these situations using Promise utilities.
Before learning these methods, make sure you understand JavaScript Promises and JavaScript Async/Await.
Promise.all() in JavaScript
The Promise.all() method takes an iterable of promises and returns a new promise that fulfills when all input promises fulfill.
If any input promise rejects, the returned promise rejects with the reason from that rejected promise. It does not wait for every remaining promise to finish before rejecting.
Syntax
Promise.all(iterable);
The iterable can contain promises, values, or other supported iterable elements. Non-promise values are treated as fulfilled values.
Example of Promise.all()
const promise1 = Promise.resolve("Apple");
const promise2 = Promise.resolve("Banana");
const promise3 = Promise.resolve("Orange");
Promise.all([promise1, promise2, promise3])
.then((results) => {
console.log(results);
})
.catch((error) => {
console.log(error);
});
Output:
["Apple", "Banana", "Orange"]
How Promise.all() Works
- It accepts multiple promises.
- It fulfills only when every input fulfills.
- It returns the results in the same order as the input promises, not the order in which they finish.
- It rejects if any input promise rejects.
Example with Promise Rejection
const promise1 = Promise.resolve("Task 1 completed");
const promise2 = Promise.reject("Task 2 failed");
const promise3 = Promise.resolve("Task 3 completed");
Promise.all([promise1, promise2, promise3])
.then((results) => {
console.log(results);
})
.catch((error) => {
console.log(error);
});
Output:
Task 2 failed
Because one promise rejects, the combined promise rejects. The other operations are not automatically cancelled and may continue running.
When to Use Promise.all()
Use Promise.all() when every operation must succeed before you can use the combined result.
For example, you might need product details, customer details, and delivery information before displaying a complete order summary.
Promise.allSettled() in JavaScript
The Promise.allSettled() method waits until every input promise has settled. A promise is settled when it either fulfills or rejects.
Unlike Promise.all(), this method does not reject simply because one of its input promises rejects. Instead, it returns an array describing the outcome of every input.
Syntax
Promise.allSettled(iterable);
Example of Promise.allSettled()
const promise1 = Promise.resolve("Task 1 completed");
const promise2 = Promise.reject("Task 2 failed");
const promise3 = Promise.resolve("Task 3 completed");
Promise.allSettled([promise1, promise2, promise3])
.then((results) => {
console.log(results);
});
Output:
[
{ status: "fulfilled", value: "Task 1 completed" },
{ status: "rejected", reason: "Task 2 failed" },
{ status: "fulfilled", value: "Task 3 completed" }
]
The exact display format may vary slightly between browsers and developer tools.
Understanding the Results
Each result object contains a status property.
| Status | Meaning | Available property |
|---|---|---|
fulfilled | The promise succeeded | value |
rejected | The promise failed | reason |
You can use these properties to process successful and failed operations separately.
Example of Handling All Results
const tasks = [
Promise.resolve("Download completed"),
Promise.reject("Upload failed"),
Promise.resolve("Backup completed")
];
Promise.allSettled(tasks).then((results) => {
results.forEach((result) => {
if (result.status === "fulfilled") {
console.log("Success:", result.value);
} else {
console.log("Error:", result.reason);
}
});
});
Output:
Success: Download completed
Error: Upload failed
Success: Backup completed
When to Use Promise.allSettled()
Use Promise.allSettled() when you need the outcome of every operation, even if some operations fail.
Common examples include:
- Processing multiple file uploads.
- Running independent background tasks.
- Checking the status of multiple API requests.
- Generating a report of successful and failed operations.
Promise.race() in JavaScript
The Promise.race() method returns a promise that settles as soon as the first input promise settles.
The first promise to settle may either fulfill or reject. Therefore, Promise.race() does not necessarily return the first successful result.
Syntax
Promise.race(iterable);
Example of Promise.race()
const promise1 = new Promise((resolve) => {
setTimeout(() => resolve("First promise"), 2000);
});
const promise2 = new Promise((resolve) => {
setTimeout(() => resolve("Second promise"), 1000);
});
Promise.race([promise1, promise2]).then((result) => {
console.log(result);
});
Output:
Second promise
The second promise fulfills after one second, while the first fulfills after two seconds. Therefore, the combined promise fulfills with "Second promise".
Example with a Rejected Promise
const promise1 = new Promise((resolve) => {
setTimeout(() => resolve("Request succeeded"), 2000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => reject("Request failed"), 500);
});
Promise.race([promise1, promise2])
.then((result) => {
console.log(result);
})
.catch((error) => {
console.log(error);
});
Output:
Request failed
The rejection happens first, so the returned promise rejects immediately after that result settles.
When to Use Promise.race()
Use Promise.race() when you need to respond to whichever promise settles first.
Examples include:
- Implementing a timeout around an operation.
- Comparing response times from different services.
- Choosing the first completed task when either success or failure should determine the outcome.
Remember that Promise.race() does not cancel the slower operations automatically. If you need to cancel a fetch request after a timeout, you can use AbortController.
Promise.any() in JavaScript
The Promise.any() method fulfills as soon as the first input promise fulfills. It ignores earlier rejections as long as another input promise eventually fulfills.
If every input promise rejects, the returned promise rejects with an AggregateError containing the individual rejection reasons.
Syntax
Promise.any(iterable);
Example of Promise.any()
const promise1 = Promise.reject("Server 1 failed");
const promise2 = new Promise((resolve) => {
setTimeout(() => resolve("Server 2 succeeded"), 1000);
});
const promise3 = new Promise((resolve) => {
setTimeout(() => resolve("Server 3 succeeded"), 2000);
});
Promise.any([promise1, promise2, promise3])
.then((result) => {
console.log(result);
})
.catch((error) => {
console.log(error);
});
Output:
Server 2 succeeded
The first promise rejects, but Promise.any() continues waiting. When the second promise fulfills, it returns that successful result without waiting for the third promise.
Example When All Promises Reject
const promise1 = Promise.reject("Server 1 failed");
const promise2 = Promise.reject("Server 2 failed");
const promise3 = Promise.reject("Server 3 failed");
Promise.any([promise1, promise2, promise3])
.then((result) => {
console.log(result);
})
.catch((error) => {
console.log(error.name);
console.log(error.errors);
});
Output:
AggregateError
["Server 1 failed", "Server 2 failed", "Server 3 failed"]
The AggregateError contains the rejection reasons from all input promises in its errors property.
When to Use Promise.any()
Use Promise.any() when you only need one successful result from multiple independent operations.
Examples include:
- Requesting the same resource from multiple available servers.
- Trying alternative services until one succeeds.
- Loading a resource from multiple fallback sources.
Difference Between Promise.all(), Promise.allSettled(), Promise.race(), and Promise.any()
These four methods have different rules for deciding when the returned promise settles.
| Method | Fulfills when | Rejects when |
|---|---|---|
Promise.all() | All inputs fulfill | Any input rejects |
Promise.allSettled() | All inputs settle | Normally does not reject due to input rejections |
Promise.race() | The first input fulfills | The first input rejects |
Promise.any() | The first input fulfills | All inputs reject |
The most important difference is how each method handles failure.
Promise.all()requires every input to succeed.Promise.allSettled()collects every input’s outcome.Promise.race()responds to the first settled promise, whether successful or failed.Promise.any()responds to the first successful promise.
Practical Example Using Promise.all() with Async/Await
You can combine Promise utilities with async and await to write cleaner asynchronous code.
Imagine an application that needs to load user details and product details from two API endpoints.
async function loadData() {
try {
const [usersResponse, productsResponse] = await Promise.all([
fetch("https://jsonplaceholder.typicode.com/users"),
fetch("https://jsonplaceholder.typicode.com/posts")
]);
if (!usersResponse.ok || !productsResponse.ok) {
throw new Error("One or more requests failed");
}
const [users, products] = await Promise.all([
usersResponse.json(),
productsResponse.json()
]);
console.log("Users:", users);
console.log("Products:", products);
} catch (error) {
console.error("Error loading data:", error.message);
}
}
loadData();
This example starts both network requests without waiting for the first one to finish before starting the second. It then parses both response bodies and handles errors.
The example checks HTTP response status explicitly because fetch() does not reject solely because the server returns an HTTP error status such as 404 or 500.
Common Mistakes When Using Promise Utilities
Assuming Promise.all() Cancels Other Promises
When one promise rejects, Promise.all() rejects, but the remaining operations are not automatically cancelled.
Use cancellation mechanisms such as AbortController when the underlying operation supports cancellation.
Confusing Promise.race() with Promise.any()
Both methods can return the first successful result if that result settles first. However, they handle an earlier rejection differently.
Promise.race() rejects if the first settled promise rejects. Promise.any() ignores individual rejections until a promise fulfills or every promise has rejected.
Assuming Promise.allSettled() Returns Only Successful Results
Promise.allSettled() returns an outcome object for every input. Check each result’s status before accessing its value or reason.
Forgetting Error Handling
When using Promise.all(), Promise.race(), or Promise.any(), include appropriate rejection handling. With Promise.any(), remember that the final error may be an AggregateError.
Thinking Promise.race() Automatically Stops Slower Operations
Promise.race() only determines the result of the combined promise. Slower requests, timers, or other operations can continue unless you explicitly cancel them.
FAQs About JavaScript Promise Utilities
What is the difference between Promise.all() and Promise.allSettled()?
Promise.all() rejects if any input promise rejects. Promise.allSettled() waits for every input to settle and returns the outcome of each promise, whether it fulfills or rejects.
What is the difference between Promise.race() and Promise.any()?
Promise.race() returns the outcome of the first settled promise, including a rejection. Promise.any() returns the first fulfilled result and rejects only when all input promises reject.
Which Promise utility should I use when all tasks must succeed?
Use Promise.all() when you need every task to fulfill before proceeding with the combined results.
Which Promise utility is best for collecting every success and failure?
Use Promise.allSettled() because it returns the status and result or rejection reason for every input promise.
What happens when Promise.any() receives an empty array?
Promise.any([]) returns a rejected promise with an AggregateError because no input promise can fulfill.
Do Promise utilities execute promises in parallel?
They allow you to coordinate asynchronous operations that have already started or are started while preparing the inputs. For example, calling multiple fetch() functions before passing their promises to Promise.all() allows the requests to progress concurrently. JavaScript does not guarantee that every kind of asynchronous operation uses CPU-parallel execution.
Conclusion
JavaScript Promise utilities make it easier to coordinate multiple asynchronous operations. Use Promise.all() when every operation must succeed, Promise.allSettled() when you need every outcome, Promise.race() when the first settled result matters, and Promise.any() when the first successful result is enough.
Understanding these methods will help you handle API requests, background tasks, fallback services, and other asynchronous workflows more effectively.