Pending
The async operation has started, but it has not completed yet.
Understand asynchronous programming, promise states, chaining, and error handling.
Learn how JavaScript handles asynchronous operations before async/await.
The async operation has started, but it has not completed yet.
The operation completed successfully and resolved with a value.
The operation failed and rejected with an error reason.
Promises help JavaScript represent work that has started but has not finished yet, like API calls, file uploads, timers, or payments.
When you order food, you do not get the result immediately. The order is pending. Later it either succeeds, or it fails. A Promise works the same way for asynchronous JavaScript work.
Order placed
Promise is pending while the kitchen prepares the food.
Food delivered
Promise is fulfilled with the meal.
Order cancelled
Promise is rejected with a reason.
Promise state flow
Promise Created
|
v
Pending
|
+-------------------+
| |
v v
Fulfilled Rejected
| |
v v
.then(value) .catch(error)
|
v
.finally(cleanup)const request = fetch("/api/products");
request
.then((response) => response.json())
.then((products) => renderProducts(products))
.catch((error) => showError(error))
.finally(() => hideLoader());A Promise constructor receives resolve and reject functions. Call resolve for success and reject for failure.
const promise = new Promise((resolve, reject) => {
resolve("Payment Successful");
});
promise.then((result) => {
console.log(result);
});Output
Payment Successful
const promise = new Promise((resolve, reject) => {
reject("Payment Failed");
});
promise.catch((error) => {
console.log(error);
});Output
Payment Failed
You start the operation now, then handle success or failure later without freezing the UI.
Bank transfer flow
Transfer Started
|
v
Processing...
|
+---------------------+
| |
v v
Money Sent Insufficient BalanceAPI call flow
Request Sent
|
v
Waiting...
|
v
Server Responds
|
v
Products Received
|
v
Display Productsfetch("/api/products")
.then((response) => response.json())
.then((products) => {
console.log(products);
})
.catch((error) => {
console.log(error);
});These methods are the main way to consume a Promise before using async/await.
Promise lifecycle
Create Promise
|
v
Pending
|
v
Success?
| |
Yes No
| |
v v
resolve() reject()
| |
v v
.then() .catch()Runs when the Promise is fulfilled.
Promise.resolve("Hello").then((result) => console.log(result));Runs when the Promise is rejected.
Promise.reject("Error").catch((error) => console.log(error));Runs whether the Promise succeeds or fails, usually for cleanup.
fetch("/api/products").finally(() => console.log("Hide Loader"));Each then() can return a value or another Promise. The next step waits for that result before running.
Promise chain
fetchUser()
|
v
.then(fetchOrders)
|
v
.then(fetchRecommendations)
|
v
.then(renderPage)
|
v
.catch(handleError)then() handles a fulfilled Promise.
catch() handles a rejected Promise.
finally() runs after success or failure.
Returning a Promise makes the next then() wait.
A settled Promise cannot change state again.
Nested callbacks become difficult to read and maintain. Promise chains make the async flow flatter and easier to handle.
getUser(function(user) {
getOrders(user, function(order) {
getPayment(order, function(payment) {
console.log(payment);
});
});
});getUser()
.then(getOrders)
.then(getPayment)
.then(console.log)
.catch(console.error);Synchronous code runs first. Promise callbacks run after the call stack is empty and before macrotasks like setTimeout.
console.log("1");
Promise.resolve().then(() => {
console.log("2");
});
console.log("3");Output
1
3
2
console.log("1") runs immediately.
Promise .then() is placed in the Microtask Queue.
console.log("3") runs immediately.
The Event Loop runs microtasks, so console.log("2") runs last.
A payment Promise keeps checkout responsive while the authorization request is processed.
console.log("Validate Card");
createPayment()
.then(() => {
console.log("Payment Approved");
})
.catch(() => {
console.log("Payment Failed");
})
.finally(() => {
console.log("Hide Spinner");
});
console.log("Show Spinner");Success
Validate Card
Show Spinner
Payment Approved
Hide Spinner
Failure
Validate Card
Show Spinner
Payment Failed
Hide Spinner
A Promise begins pending, then settles into either fulfilled or rejected.
Promises power everyday async workflows across frontend, backend, and commerce systems.
Fetch product, account, and content data without blocking the UI.
Track upload progress, completion, and upload failures with promise states.
Chain validation, authorization, capture, and error recovery safely.
Coordinate checkout calls and render confirmation only after success.
Send non-blocking events while keeping the shopping journey responsive.
Checkout and product journeys are full of async operations that need clean state, success, and failure paths.
Debounced search returns a Promise that resolves with matching products.
Parallel inventory calls resolve before rendering availability badges.
Shipping, payment, and address promises determine whether checkout can continue.
Rejected promises surface recoverable payment errors.
Fulfilled order placement promises render receipt and confirmation details.
async/await is built on top of Promises and often makes asynchronous code easier to read.
// Using Promises
fetch("/api/products")
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.log(error));
// Using async/await
async function getProducts() {
try {
const response = await fetch("/api/products");
const data = await response.json();
console.log(data);
} catch (error) {
console.log(error);
}
}Promises make asynchronous JavaScript easier to read, chain, and recover from.
Deeply nested callbacks
Harder error handling
Less readable code
Cleaner asynchronous code
Better error handling with .catch()
Easy chaining with .then()
Works seamlessly with async/await
Use this answer when someone asks what a Promise is.
A Promise is a JavaScript object that represents the eventual result of an asynchronous operation. It starts in the Pending state and eventually becomes either Fulfilled by calling resolve() or Rejected by calling reject(). We consume Promises using .then(), .catch(), and .finally(), or with async/await. Promise callbacks are executed through the Microtask Queue, which the Event Loop processes before Macrotasks like setTimeout().
Detailed answers for Promise fundamentals, state transitions, chaining, and concurrency.
A Promise is a JavaScript object representing the eventual result of an asynchronous operation. It starts pending, then becomes fulfilled with a value or rejected with an error.
A Promise has three states: pending, fulfilled, and rejected. Once it settles as fulfilled or rejected, that state is final and cannot change.
Promise.all waits for every promise to fulfill and rejects if any promise rejects. Promise.race settles as soon as the first promise fulfills or rejects.
Errors thrown inside a then callback or promises that reject move to the nearest catch handler. finally runs after settlement and is useful for cleanup like hiding loaders.
Promise chaining connects async steps by returning a value or another promise from each then callback. The next then waits for that returned promise before running.