JavaScript Promises
Promises are a core concept in modern JavaScript, especially when working with asynchronous operations like API calls, file handling, and timers. Understanding promises deeply will help you write cleaner, more maintainable, and scalable code.
What is a Promise?
A Promise in JavaScript is an object that represents the future result of an asynchronous operation. Instead of returning a value immediately, it acts as a placeholder that will eventually resolve with a result or reject with an error. This allows developers to write cleaner, more manageable code when dealing with tasks like API calls or timers. Promises help avoid deeply nested callbacks and improve readability by using methods like ‘.then()’, ‘.catch()’, and ‘.finally()’ to handle success, failure, and completion of asynchronous operations in a structured way.
Why Promises are Important?
In earlier JavaScript, developers relied heavily on callbacks to handle asynchronous operations like API calls and timers. While callbacks worked, they often resulted in deeply nested functions, making the code difficult to read, debug, and maintain. This messy structure is commonly known as callback hell. As more asynchronous tasks were added, the code became increasingly complex and harder to follow. Managing errors across multiple callback levels also became challenging.
Promises solve this problem by:
- Providing structured flow
- Enabling chaining
- Improving readability
- Handling errors efficiently
States of a Promise
Every promise goes through three states:
1. Pending – Initial state, operation not completed
2. Fulfilled – Operation completed successfully
3. Rejected – Operation failed
Once a promise is fulfilled or rejected, it becomes immutable (cannot change again).
Creating a Promise
const myPromise = new Promise((resolve, reject) => {
let success = true;
if (success) {
resolve(“Data loaded successfully”);
} else {
reject(“Error loading data”);
}
});
Here:
‘resolve()’ is called when the operation succeeds
‘reject()’ is called when it fails
Consuming a Promise
You can handle the result using ‘.then()’ , ‘.finally()’ and ‘.catch()’:
Here’s a clear breakdown of each function in your Promise chain:
myPromise
.then((result) => {
console.log(result);
})
.catch((error) => {
console.log(error);
})
.finally(() => {
console.log(“Execution completed”);
});
‘.then()’ – It handles the successful result of the promise. It runs when the promise is fulfilled and receives the resolved value as its argument. You typically use it to process or display the data returned from an async operation.
‘.catch()’ – It handles any errors or rejections in the promise chain. It runs if the promise fails or if an error occurs inside ‘.then()’. This ensures your application doesn’t crash and errors are managed properly.
‘.finally()’ – It executes regardless of success or failure of the promise. It does not receive any value or error as an argument. Commonly used for cleanup tasks like stopping loaders or closing connections after execution.
Real-Life Example: Ordering Food Online
You order food from an app:
- Order placed → Pending
- Food delivered → Resolved
- Order canceled → Rejected
function orderFood(item) {
return new Promise((resolve, reject) => {
console.log(“Order placed for:”, item);
setTimeout(() => {
const restaurantOpen = true;
if (restaurantOpen) {
resolve(“Your ” + item + ” has been delivered “);
} else {
reject(“Sorry, restaurant is closed “);
}
}, 2000);
});
}
// Consuming the promise
orderFood(“Pizza”)
.then(message => {
console.log(message);
})
.catch(error => {
console.log(error);
})
.finally(() => {
console.log(“Thank you for using our service “);
});
Output
Order placed for: Pizza
(After 2 seconds)
Your Pizza has been delivered
Thank you for using our service
If Order Fails
Change:
const restaurantOpen = false;
Output
Order placed for: Pizza
Sorry, restaurant is closed
Thank you for using our service
What You Learned
- ‘resolve()’ – success (food delivered)
- ‘reject()’ – failure (order canceled)
- ‘.then()’ – handle success
- ‘.catch()’ – handle error
- ‘.finally()’ – always runs
Promises have become a fundamental part of modern JavaScript for handling asynchronous operations in a clean and structured way. They eliminate the complexity of callback hell and make code easier to read, write, and maintain. By using ‘.then()’, ‘.catch()’, and ‘.finally()’, developers can efficiently manage success, errors, and completion of tasks.
Promises also serve as the foundation for ‘async/await’, further simplifying asynchronous code. Understanding promises is essential for working with APIs, handling data, and building scalable applications. This enables developers to write more efficient, reliable, and professional JavaScript code in real-world projects.