JavaScript is a single-threaded language, meaning it can only execute one task at a time. However, modern applications require handling multiple tasks asynchronously, such as fetching data from a server or reading files. This is where Promises come into play.
» What is a Promise?
A Promise in JavaScript is an object that represents the eventual completion (or failure) of an asynchronous operation. It acts as a placeholder for the result of a task that will finish sometime in the future.
» States of a Promise
A JavaScript Promise has three states:
- Pending – The initial state; the operation is still in progress.
- Fulfilled – The operation was successful, and a result is available.
- Rejected – The operation failed, and an error is available.
Once a promise is either fulfilled or rejected, it is considered settled and cannot change states again.
» Creating a Promise
You can create a Promise using the Promise constructor, which takes a function (executor) with two parameters: resolve and reject.
const myPromise = new Promise((resolve, reject) => {
let success = true;
setTimeout(() => {
if (success) {
resolve("Operation Successful!")
} else {
reject("Operation Failed!")
}
}, 2000);
});
» Handling a Promise
Once a Promise is created, we can handle its result using .then(), .catch(), and .finally() methods.
» Using .then()
The .then() method runs when a promise is resolved.
myPromise.then((message) => {
console.log(message) // Output after 2 seconds: Operation Successful!
});
» Using .catch()
If the promise is rejected, .catch() handles the error.
myPromise.then((message) => {
console.log(message)
}).catch((error) => {
console.log(error)
});
» Using .finally()
The .finally() method executes regardless of whether the promise was resolved or rejected.
myPromise.then((message) => {
console.log(message)
}).catch((error) => {
console.log(error)
}).finally(() => {
console.log("Operation Completed.")
})
» Chaining Promises
Promises can be chained to run multiple asynchronous operations in sequence.
new Promise((resolve, reject) => {
setTimeout(() => resolve(10), 1000);
}).then((num) => {
console.log(num); // 10
return num * 2;
}).then((num) => {
console.log(num); // 20
return num * 3;
}).then((num) => {
console.log(num) // 60
}).catch((error) => {
console.log(error)
})
» Promise Methods
→ Promise.all()
Executes multiple promises in parallel and waits for all of them to complete. If any promise fails, it rejects the entire operation.
Promise.all([
Promise.resolve("Task 1 completed"),
Promise.resolve("Task 2 completed"),
Promise.resolve("Task 3 completed"),
]).then((results) => {
console.log(results)
}).catch((error) => {
console.log(error)
});
→ Promise.race()
Returns the result of the first settled promise (resolved or rejected).
Promise.race([
new Promise((resolve) => setTimeout(() => resolve("Fast task"), 1000)),
new Promise((resolve) => setTimeout(() => resolve("Slow task"), 3000)),
]).then((result) => {
console.log(result)
}); // "Fast task"
→ Promise.allSettled()
Waits for all promises to settle (either fulfilled or rejected) and returns their results.
Promise.allSettled([
Promise.resolve("Success"),
Promise.reject("Error"),
Promise.resolve("Another success"),
]).then((results) => {
console.log(results)
});
→ Promise.any()
Returns the first fulfilled promise, ignoring rejected ones.
Promise.any([
Promise.reject("Error 1"),
Promise.reject("Error 2"),
Promise.resolve("Success"),
]).then((result) => {
console.log(result)
}); // "Success"
→ Async/Await: The Modern Way
Instead of chaining .then(), JavaScript introduced async/await to write cleaner asynchronous code.
async function fetchData() {
try {
let result = await myPromise;
console.log(result);
} catch (error) {
console.log(error);
}
}
fetchData();
» Conclusion
Promises are a powerful tool in JavaScript for handling asynchronous operations efficiently. By understanding how to create, handle, and chain promises, you can write clean, non-blocking code that improves performance and user experience. Happy coding!