A Promise is an object representing the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of it as a “placeholder” for a value that hasn’t arrived yet.
.then, .catch, .finally)When a promise is returned (like from a network request), we use handlers to deal with the result.
JavaScript
const myPromise = new Promise((resolve, reject) => {
let success = true;
if (success) {
resolve("Data received!");
} else {
reject("Error: Connection lost.");
}
});
myPromise
.then((data) => console.log(data)) // Runs if Resolved
.catch((err) => console.error(err)) // Runs if Rejected
.finally(() => console.log("Done")); // Runs always
fetch() is the modern way to make HTTP requests (API calls). It returns a Promise.
Crucial Note: A fetch() promise only rejects if there is a network error. It does not reject for 404 or 500 errors. You must check the response.ok property.
JavaScript
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then(response => {
if (!response.ok) throw new Error("HTTP error " + response.status);
return response.json(); // .json() also returns a promise!
})
.then(data => console.log(data))
.catch(error => console.error("Request Failed:", error));
One of the best features of Promises is that you can chain them. Each .then() returns a new promise, allowing you to process data in steps.
JavaScript
getUser(1)
.then(user => getPosts(user.id))
.then(posts => getComments(posts[0].id))
.then(comments => console.log(comments))
.catch(err => console.log(err)); // One catch for the whole chain!
Sometimes you need to trigger multiple requests at once. JavaScript provides static methods for this:
| Method | Behavior |
Promise.all([p1, p2]) | Waits for all to succeed. If one fails, the whole thing fails immediately. |
Promise.allSettled([p1, p2]) | Waits for all to finish, regardless of success or failure. Returns an array of results. |
Promise.race([p1, p2]) | Returns the result of the first promise to settle (fastest one wins). |
Promise.any([p1, p2]) | Returns the first successful promise. If all fail, it throws an error. |
Before promises, we had nested functions inside functions. Promises flatten this structure, making the code much more readable.
Let’s say you want to get a User and their Posts at the same time to save time.
JavaScript
const userReq = fetch('https://api.example.com/user/1');
const postReq = fetch('https://api.example.com/user/1/posts');
Promise.all([userReq, postReq])
.then(responses => {
// Convert both responses to JSON
return Promise.all(responses.map(res => res.json()));
})
.then(([userData, postData]) => {
console.log("User:", userData);
console.log("Posts:", postData);
})
.catch(err => console.error("One of the requests failed", err));
Modern applications constantly:
Promises provide a clean, predictable, and composable way to handle async code.
Promises solve:
A Promise is an object that represents:
The eventual completion or failure of an asynchronous operation.
| State | Meaning |
|---|---|
| Pending | Initial state |
| Fulfilled | Resolved successfully |
| Rejected | Failed |
A promise is settled once fulfilled or rejected.
resolve and reject.then().catch().finally()| Pattern | Use Case |
|---|---|
| Sequential | Dependent calls |
| Parallel | Independent APIs |