JavaScript Promises: What They Are, How They Work, and Why They Matter

What is a Promise?
A Promise is a built-in JavaScript object that represents the eventual completion (or failure) of an asynchronous operation and its resulting value.
In simple words, a Promise is something that promises to do a task and lets you handle what happens after it’s done — whether it was successful or not.
Lets understand with a analogy →
Imagine ordering a pizza online.
You place the order.
The restaurant gives you a promise that your pizza will be delivered.
This promise can be in 3 states:
Pending: Pizza is being prepared.
Fulfilled: Pizza is delivered.
Rejected: Order failed, no pizza for you.
Once the promise is fulfilled or rejected, you act accordingly — enjoy the pizza or order from somewhere else.
🚦 The Three States of a Promise
Pending: The initial state. Task is still running.
Fulfilled: Task completed successfully. You get the result.
Rejected: Task failed. You get an error.
Syntax: How to Create a Promise
const myPromise = new Promise(function(resolve, reject) {
// async task here
});
What's resolve
and reject
?
resolve(value)
→ Call this when your async task completes successfully.reject(error)
→ Call this when something goes wrong.
These are just callback functions passed into your Promise
constructor — you control when to call them based on what happens inside the async task.
4 Practical Ways to Create and Use Promises
Example 1: Basic Async Task
const promiseOne = new Promise(function(resolve, reject){
setTimeout(function(){
console.log('Async task is complete');
resolve();
}, 1000);
});
promiseOne.then(function(){
console.log("Promise consumed");
});
This prints:
Async task is complete
Promise consumed
Example 2: Shorthand Inline Promise
new Promise(function(resolve, reject){
setTimeout(function(){
console.log("Async task 2");
resolve();
}, 1000);
}).then(function(){
console.log("Async 2 resolved");
});
No variable needed if you're chaining immediately.
Example 3: Passing Data via resolve()
const promiseThree = new Promise(function(resolve, reject){
setTimeout(function(){
resolve({ username: "Chai", email: "chai@example.com" });
}, 1000);
});
promiseThree.then(function(user){
console.log(user); // { username: "Chai", email: "chai@example.com" }
});
Example 4: Handling Errors with .catch()
const promiseFour = new Promise(function(resolve, reject){
setTimeout(function(){
let error = true;
if (!error) {
resolve({ username: "hitesh", password: "123" });
} else {
reject('ERROR: Something went wrong');
}
}, 1000);
});
promiseFour
.then((user) => {
console.log(user);
return user.username;
})
.then((username) => {
console.log(username);
})
.catch((error) => {
console.log(error);
})
.finally(() => {
console.log("The promise is either resolved or rejected");
});
Understanding .then()
, .catch()
, and .finally()
→.then(callback)
Runs when the Promise is fulfilled (i.e., resolved).
promise.then(result => {
console.log("Got result:", result);
});
→ .catch(callback)
Runs when the Promise is rejected (i.e., an error occurred).
promise.catch(error => {
console.log("Caught error:", error);
});
→.finally(callback)
Runs no matter what — whether the promise was resolved or rejected.
promise.finally(() => {
console.log("Cleanup complete!");
});
Useful for hiding loaders, closing modals, etc.
Using Promises with async/await
You can make your code look synchronous using async/await
.
const promiseFive = new Promise(function(resolve, reject){
setTimeout(function(){
let error = true;
if (!error) {
resolve({ username: "javascript", password: "123" });
} else {
reject('ERROR: JS went wrong');
}
}, 1000);
});
async function consumePromiseFive(){
try {
const response = await promiseFive;
console.log(response);
} catch (error) {
console.log(error);
}
}
consumePromiseFive();
Cleaner, more readable — and highly recommended.
What Does console.log(promise)
Show?
It shows the current state of the Promise:
Promise { <pending> }
Promise { <fulfilled>: value }
Promise { <rejected>: reason }
Depending on whether it’s still running, succeeded, or failed.
Bonus: Promise.all()
Want to run multiple async tasks in parallel and wait for all to finish?
Promise.all([promise1, promise2])
.then((results) => {
console.log(results); // [result1, result2]
})
.catch((error) => {
console.log("One promise failed:", error);
});
⚠️ If any one fails, the whole thing rejects.
TL;DR
Concept | Description |
Promise | A placeholder for future value from an async task |
States | pending , fulfilled , rejected |
resolve() | Call when task succeeds |
reject() | Call when task fails |
.then() | Runs on success |
.catch() | Runs on error |
.finally() | Runs either way (cleanup) |
async/await | Makes promise handling look synchronous |
Final Thoughts
Learning promises can feel a bit abstract at first — but once you understand the lifecycle and how to handle success/failure, you’ll unlock the full power of async programming in JavaScript.
Whether you're fetching APIs, handling files, or dealing with database calls — Promises are your async best friend.
Subscribe to my newsletter
Read articles from VANSH KANSAL directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
