JavaScript Promises
A Promise is an object that represents the eventual result of an asynchronous operation. Instead of receiving a result immediately, a promise says: "I will give the result later — either successfully or with an error."
Real-life analogy: When ordering food at a restaurant, a receipt is given — a promise that food will arrive. It may succeed (food delivered) or fail (item unavailable). While waiting, other activities can continue.
Why Promises?
Before promises, asynchronous operations relied on callbacks — functions passed into other functions to run after completion. Deeply nested callbacks created what is called "callback hell," making code difficult to read and maintain.
// Callback hell — hard to read and manage
getUser(id, function(user) {
getOrders(user.id, function(orders) {
getOrderDetails(orders[0], function(details) {
getInvoice(details, function(invoice) {
console.log(invoice); // Deeply nested!
});
});
});
});Promises solve this with a clean chain-based syntax.
Promise States
A promise can be in one of three states:
| State | Meaning |
|---|---|
| Pending | Initial state — operation not yet complete |
| Fulfilled | Operation completed successfully |
| Rejected | Operation failed with an error |
Once fulfilled or rejected, a promise is settled and its state cannot change.
Creating a Promise
let myPromise = new Promise(function(resolve, reject) {
// Simulate an async operation
let success = true;
if (success) {
resolve("Operation completed!"); // Fulfill the promise
} else {
reject("Something went wrong."); // Reject the promise
}
});Consuming a Promise — .then(), .catch(), .finally()
myPromise
.then(function(result) {
console.log("Success:", result);
})
.catch(function(error) {
console.log("Error:", error);
})
.finally(function() {
console.log("Promise settled.");
});With Arrow Functions (Modern Style)
myPromise
.then(result => console.log("Success:", result))
.catch(error => console.log("Error:", error))
.finally(() => console.log("Done."));Promise with a Delay — Simulating Async Operations
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
let data = { user: "Neha", score: 92 };
resolve(data);
}, 2000); // Simulates a 2-second API call
});
}
fetchData()
.then(data => {
console.log("Data received:", data.user, data.score);
})
.catch(err => {
console.log("Failed:", err);
});
console.log("Waiting for data..."); // Runs first while promise is pendingPromise Chaining
Multiple asynchronous operations can be chained using .then(). Each .then() receives the result of the previous one and returns a new promise.
function step1() {
return new Promise(resolve => setTimeout(() => resolve("Step 1 done"), 1000));
}
function step2(prev) {
return new Promise(resolve => setTimeout(() => resolve(prev + " → Step 2 done"), 1000));
}
function step3(prev) {
return new Promise(resolve => setTimeout(() => resolve(prev + " → Step 3 done"), 1000));
}
step1()
.then(result => step2(result))
.then(result => step3(result))
.then(finalResult => console.log(finalResult))
.catch(err => console.log("Error:", err));
// After 3 seconds:
// Step 1 done → Step 2 done → Step 3 doneRejecting and Catching Errors in Chains
function validateAge(age) {
return new Promise((resolve, reject) => {
if (age >= 18) {
resolve("Access granted!");
} else {
reject("You must be 18 or older.");
}
});
}
validateAge(15)
.then(msg => console.log(msg))
.catch(err => console.log("Rejected:", err));
// Rejected: You must be 18 or older.Promise.all() — Run Multiple Promises Simultaneously
Promise.all() takes an array of promises and waits for all of them to resolve. If any one fails, the entire call rejects.
let p1 = new Promise(resolve => setTimeout(() => resolve("Data A"), 1000));
let p2 = new Promise(resolve => setTimeout(() => resolve("Data B"), 500));
let p3 = new Promise(resolve => setTimeout(() => resolve("Data C"), 800));
Promise.all([p1, p2, p3])
.then(results => {
console.log(results); // ["Data A", "Data B", "Data C"]
})
.catch(err => console.log("One failed:", err));Promise.allSettled() — Wait for All, Regardless of Outcome
Promise.allSettled() waits for all promises to finish and returns all outcomes, both fulfilled and rejected.
let p1 = Promise.resolve("Success!");
let p2 = Promise.reject("Failed!");
let p3 = Promise.resolve("Also success!");
Promise.allSettled([p1, p2, p3]).then(results => {
results.forEach(result => {
if (result.status === "fulfilled") {
console.log("Fulfilled:", result.value);
} else {
console.log("Rejected:", result.reason);
}
});
});
// Fulfilled: Success!
// Rejected: Failed!
// Fulfilled: Also success!Promise.race() — First One Wins
Promise.race() resolves or rejects as soon as the first promise settles.
let fast = new Promise(resolve => setTimeout(() => resolve("Fast!"), 300));
let slow = new Promise(resolve => setTimeout(() => resolve("Slow!"), 1000));
Promise.race([fast, slow])
.then(winner => console.log("Winner:", winner));
// Winner: Fast!Promise.any() — First Successful One
Promise.any() resolves with the first fulfilled promise. It only rejects if all promises fail.
let p1 = Promise.reject("Failed 1");
let p2 = Promise.resolve("Success!");
let p3 = Promise.reject("Failed 3");
Promise.any([p1, p2, p3])
.then(result => console.log("First success:", result));
// First success: Success!Promise Methods Comparison
| Method | Resolves When | Rejects When |
|---|---|---|
| Promise.all() | All promises fulfill | Any one rejects |
| Promise.allSettled() | All promises settle (always) | Never rejects |
| Promise.race() | First promise settles | First promise rejects |
| Promise.any() | First promise fulfills | All promises reject |
Practical Example — Simulated User Login
function checkCredentials(username, password) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (username === "admin" && password === "1234") {
resolve({ userId: 101, name: "Admin User" });
} else {
reject("Invalid username or password.");
}
}, 1500);
});
}
checkCredentials("admin", "1234")
.then(user => {
console.log(`Welcome, ${user.name}! (ID: ${user.userId})`);
})
.catch(err => {
console.log("Login failed:", err);
})
.finally(() => {
console.log("Login attempt complete.");
});
// Welcome, Admin User! (ID: 101)
// Login attempt complete.Key Points to Remember
- A Promise represents a future value — either fulfilled (success) or rejected (failure)
- Use
.then()to handle success,.catch()for errors, and.finally()for cleanup - Promises can be chained to handle sequential async operations cleanly
Promise.all()waits for all to succeed; fails if any one failsPromise.allSettled()waits for all regardless of outcomePromise.race()resolves with the first settled promisePromise.any()resolves with the first fulfilled promise- Always handle errors with
.catch()to prevent unhandled rejection warnings
