Promises in JavaScript
A Promise is an object representing the eventual completion or failure of an asynchronous operation. It provides a more manageable alternative to callbacks for handling async tasks.
1. Promise States
A Promise can be in one of three states:
- Pending: The initial state; the operation is ongoing.
- Fulfilled: The operation completed successfully, with a result.
- Rejected: The operation failed, with an error.
2. Creating a Promise
- resolve(value) → Marks the promise as fulfilled.
- reject(reason) → Marks the promise as rejected.
const promise = new Promise((resolve, reject) => {
// Async operation here
const success = true; // example condition
if (success) {
resolve("Operation successful!");
} else {
reject("Operation failed!");
}
});
3. Consuming Promises
a) .then()
- Handles the fulfilled result of the Promise.
- Optionally handles rejection (if no .catch is used).
promise.then(result => {
console.log(result); // "Operation successful!"
});
b) .catch()
Handles errors (rejections) from the Promise or any preceding .then.
promise.catch(error => {
console.error(error); // "Operation failed!"
});
c) .finally()
Runs a callback regardless of whether the Promise is fulfilled or rejected.
promise.finally(() => {
console.log("Promise settled");
});
4. Chaining Promises
You can chain multiple .then()
calls. Each .then()
returns a new promise.
new Promise((resolve) => {
resolve(5);
})
.then(result => result * 2)
.then(result => result + 3)
.then(result => console.log(result)); // 13
5. Handling Errors in Chains
Errors propagate down the chain until a .catch()
handles them.
new Promise((resolve, reject) => {
reject("Something went wrong");
})
.then(result => console.log(result))
.catch(error => console.error("Caught:", error)); // "Caught: Something went wrong"
6. Promise Combinators
a) Promise.all(iterable)
Waits for all promises to fulfill; rejects if any promise rejects.
Promise.all([
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve(3)
]).then(results => console.log(results)); // [1, 2, 3]
b) Promise.allSettled(iterable)
Waits for all promises to settle (fulfilled or rejected) and returns their results.
Promise.allSettled([
Promise.resolve(1),
Promise.reject("Error"),
]).then(results => console.log(results));
/*
[
{ status: 'fulfilled', value: 1 },
{ status: 'rejected', reason: 'Error' }
]
*/
c) Promise.race(iterable)
Returns the result of the first promise to settle (fulfilled or rejected).
Promise.race([
new Promise(res => setTimeout(() => res("A"), 1000)),
new Promise(res => setTimeout(() => res("B"), 500))
]).then(result => console.log(result)); // "B"
d) Promise.any(iterable)
Returns the first fulfilled promise; ignores rejected promises (ES2021+).
Promise.any([
Promise.reject("Error1"),
Promise.resolve("Success"),
Promise.reject("Error2")
]).then(result => console.log(result)); // "Success"
7. Converting Callbacks to Promises
Many old-style callback APIs can be wrapped in promises:
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
delay(1000).then(() => console.log("1 second passed"));
8. Async/Await Syntax with Promises
async/await
provides syntactic sugar for handling promises in a synchronous-like manner.
async function fetchData() {
try {
const response = await fetch("https://api.example.com/data");
const data = await response.json();
console.log(data);
} catch (error) {
console.error("Error:", error);
}
}
fetchData();