JavaScript - Promises
JavaScript Promises are a powerful tool for managing asynchronous operations. They represent a value that may be available now, in the future, or never. Promises are a modern alternative to traditional callback-based approaches, making code easier to read and maintain.
1. What is a Promise?
A Promise is an object representing the eventual completion (or failure) of an asynchronous operation. It is used to handle asynchronous tasks like fetching data, reading files, or waiting for a timer to expire.
2. States of a Promise
Promises have three states:
Pending: The initial state, neither fulfilled nor rejected.
Fulfilled: The operation completed successfully, and the promise has a result.
Rejected: The operation failed, and the promise has a reason for failure.
3. Creating a Promise
You can create a promise using the Promise constructor, which takes a function with two parameters: resolve and reject.
Example:
const myPromise = new Promise((resolve, reject) => {
let condition = true; // Change to false to test rejection
if (condition) {
resolve("The promise was fulfilled!");
} else {
reject("The promise was rejected!");
}
});
// Logging the promise
console.log(myPromise);
4. Using .then() and .catch()
Consuming a Promise:
Use .then() to handle the resolved value and .catch() to handle errors.
Example:
myPromise
.then((message) => {
console.log(message); // Logs: "The promise was fulfilled!"
})
.catch((error) => {
console.error(error); // Logs: "The promise was rejected!"
});
5. Chaining Promises
Promises can be chained for sequential asynchronous operations. Each .then() returns a new promise, allowing multiple operations to be linked.
Example:
const fetchData = new Promise((resolve, reject) => {
resolve(10);
});
fetchData
.then((data) => {
console.log(`Step 1: ${data}`);
return data * 2; // Pass to the next .then()
})
.then((data) => {
console.log(`Step 2: ${data}`);
return data + 5;
})
.then((data) => {
console.log(`Step 3: ${data}`);
})
.catch((error) => {
console.error("Error:", error);
});
6. The .finally() Method
The .finally() method is called regardless of whether the promise is resolved or rejected. It's useful for cleanup tasks.
Example:
fetchData
.then((data) => {
console.log(`Data: ${data}`);
})
.catch((error) => {
console.error("Error:", error);
})
.finally(() => {
console.log("Operation completed.");
});
7. Handling Multiple Promises
Promise.all()
Waits for all promises to resolve and returns an array of results. If any promise is rejected, the entire operation fails.
const promise1 = Promise.resolve("First");
const promise2 = Promise.resolve("Second");
const promise3 = Promise.resolve("Third");
Promise.all([promise1, promise2, promise3])
.then((results) => {
console.log(results); // Logs: ["First", "Second", "Third"]
})
.catch((error) => {
console.error("Error:", error);
});
Promise.race()
Returns the result of the first promise to resolve or reject.
const slowPromise = new Promise((resolve) => setTimeout(() => resolve("Slow"), 2000));
const fastPromise = new Promise((resolve) => setTimeout(() => resolve("Fast"), 1000));
Promise.race([slowPromise, fastPromise])
.then((result) => {
console.log(result); // Logs: "Fast"
});
8. Common Mistakes and Best Practices
Mistakes:
Forgetting to handle rejections: Always include a .catch() block.
Returning undefined in .then(): Ensure to return values for chaining.
Mixing callbacks and promises: Stick to one pattern for cleaner code.
Best Practices:
Use async/await for cleaner syntax when handling promises.
Use Promise.allSettled() to handle arrays of promises where failures should not interrupt the process.
Handle exceptions properly to avoid unhandled rejections.
9. Conclusion
Promises are an integral part of modern JavaScript, simplifying the management of asynchronous tasks. By mastering promises, you can write cleaner, more reliable, and maintainable code.
Key Takeaways:
Use .then() for resolved promises and .catch() for errors.
Chain promises for sequential operations.
Handle multiple promises with Promise.all() or Promise.race().
Leverage .finally() for cleanup tasks.