JavaScript Promises: then, catch and Promise.all()
A JavaScript Promise represents the eventual result of an asynchronous operation. Learn how to handle a fulfilled or rejected Promise with .then() and .catch(), and how to coordinate independent work with Promise.all().
Quick answer: A Promise starts pending, then becomes fulfilled with a value or rejected with a reason. Attach .then() for a successful result and .catch() for errors. Use await as another way to write code that waits for a Promise.
Handle a Promise with then and catch
Many browser APIs return Promises. The fetch() function is one example. Return the next asynchronous step from .then() so the following handler receives its result.
fetch("data/items.json")
.then(response => {
if (!response.ok) {
throw new Error(`Request failed: ${response.status}`);
}
return response.json();
})
.then(items => {
console.table(items);
})
.catch(error => {
console.error("Could not load items:", error);
});
The first .then() checks the HTTP status and returns another Promise for the parsed JSON. The next .then() receives the data. A rejection or thrown error in the chain reaches .catch().
Run independent Promises together
When two tasks do not depend on one another, Promise.all() can wait for both concurrently. It fulfills with results in the same order as the input array. If any input rejects, the returned Promise rejects.
async function loadPageData() {
const [profileResponse, postsResponse] = await Promise.all([
fetch("data/profile.json"),
fetch("data/posts.json")
]);
if (!profileResponse.ok || !postsResponse.ok) {
throw new Error("One or more requests failed.");
}
const [profile, posts] = await Promise.all([
profileResponse.json(),
postsResponse.json()
]);
return { profile, posts };
}
Use Promise.all() when each task can begin without another task’s result. If the second request needs a value from the first, await them in sequence instead. The example files profile.json and posts.json are included beside this lesson. Handle network and parsing errors at the call site.
Promise.all or Promise.allSettled?
Choose Promise.all() when the complete set of results is required and a single failure should reject the group. Choose Promise.allSettled() when you need to inspect every outcome, including tasks that failed, without stopping at the first rejection.
Promise questions
Does fetch reject when a server returns 404?
Usually, no. A response with an HTTP error status still fulfills the fetch Promise. Check response.ok and handle an unsuccessful status explicitly.
Do I need to create a Promise with new Promise?
Usually not when using an API that already returns a Promise. Create one only when adapting a callback-based operation or controlling a custom asynchronous task. Wrapping an existing Promise in another Promise often adds unnecessary complexity.
Practice: load two independent resources
Make two small JSON files beside an HTML page. Fetch both with Promise.all(), check each response’s ok property, and display the combined result. Then temporarily change one path and confirm your error handling explains what went wrong.