Why Do We Even Need Promises?
🕰️ Problem: JavaScript is primarily synchronous, running one piece of code at a time.
Imagine JS as a one-man band — it can only do one thing at a time. But the world (like APIs, file reading, or user clicks) doesn't wait.
Let’s say:
You fetch data from a server.
It takes 2 seconds.
Meanwhile, your app shouldn’t freeze.
So we need a way to wait without blocking other work.
i think now we are clear about the problem right ? ok now lets understand about what exactly is promise.
🧃 The Juice Shop Analogy: Understanding Promises
Imagine you're at a juice shop:
You place an order for a mango juice.
The shopkeeper says, "It'll be ready in 5 minutes."
You receive a token and wait.
After 5 minutes:
If the juice is ready, you get it. ✅
If mangoes are out of stock, you're informed. ❌
In JavaScript, this scenario shows how Promises work.
🧠 So, What is a Promise in JavaScript?
A Promise is like a "contract" that says:
“I promise to give you something in the future — either a success or a failure.”
🔄 The 3 States of a Promise:
JavaScript Promise States
State | Meaning |
---|---|
🕒 Pending | Still waiting. Not ready yet. |
✅ Fulfilled | Promise kept. Success! Got the result. |
❌ Rejected | Something went wrong. It failed. |
🧪 Let’s Try a Simple Example (No need to panic)
const juicePromise = new Promise((resolve, reject) => {
let mangoes = true;
if (mangoes) {
resolve("Here is your mango juice!");
} else {
reject("Sorry, no mangoes today.");
}
});
juicePromise
.then(result => console.log(result)) // when successful
.catch(error => console.log(error)); // when failed
⏱️ Why Use Promises?
Because JavaScript is single-threaded. That means it can only do one thing at a time. So if you wait 5 seconds to get data from a server, JavaScript would freeze your whole website.
Promises let JS do something else while waiting.
😵💫 Old Way: Callback Hell (Before Promises)
getData(function(result) {
processData(result, function(final) {
displayData(final, function() {
// more and more nesting 😭
});
});
});
Too many () inside () inside () = messy and hard to read.
🦸♂️ Superhero: Promises to the Rescue
getData()
.then(processData)
.then(displayData)
.catch(error => console.log(error));
Cleaner, right? 😊
🧱 Let's Understand Promise Chaining
Every .then() returns a new promise. You can chain .then() to run things in order.
function first() {
return new Promise(resolve => setTimeout(() => resolve("Step 1 done"), 1000));
}
function second(data) {
return new Promise(resolve => setTimeout(() => resolve(data + " → Step 2 done"), 1000));
}
first()
.then(result => second(result))
.then(final => console.log(final));
Output: Step 1 done → Step 2 done (after 2 seconds)
🔃 What is async/await and Why is it Cool?
Problem: .then() is better than callbacks, but still not very “human-friendly”.
Let’s rewrite using async/await (which works on top of promises):
function getJuice() {
return new Promise(resolve => {
setTimeout(() => {
resolve("Here's your juice!");
}, 2000);
});
}
async function serveJuice() {
console.log("Ordering juice...");
const result = await getJuice(); // wait until juice is ready
console.log(result);
}
serveJuice();
output:
Ordering juice...
(wait 2 sec)
Here's your juice!
Why it’s easier?
- No .then()
- Looks like normal code, but still async!
- Easier to debug and read
⚡ Parallel vs Sequential
const user = await getUser(); // wait 1 sec
const posts = await getPosts(); // wait 1 sec
Takes 2 seconds total right ? yes it will took 2 sec but what if we can do this same thing in 1 sec ? yes you heard it right . we can do same thing in 1 sec and that's parallel way.
✅ Parallel: Run together
const [user, posts] = await Promise.all([getUser(), getPosts()]);
Takes 1 second only!
❌ Mixing await with normal functions
await getSomething(); // ❌ ERROR if not inside async
async function doIt() {
await getSomething(); // ✅
}
lets try to recall all of the above things and know the things to handle the asynchronous events in JS.
🕰️ Evolution of Asynchronous Handling in JavaScript
1)📞 Callbacks (The Beginning)
What is it?
- A function passed as an argument to be called after another function finishes.
- The earliest way to handle async behavior in JavaScript.
Problem:
- Callback Hell (nested pyramid of doom).
- Hard to read, debug, and maintain.
example:
function getData(callback) {
setTimeout(() => {
callback("📦 Data received");
}, 1000);
}
getData(function(result) {
console.log(result);
});
2)🔮 Promises (Introduced in ES6 - 2015)
What is it?
An object that represents a value that may not be available yet, but will be resolved in the future.
Uses .then() for success and .catch() for errors.
Improvement:
- Avoids nesting by using chaining.
- Easier error handling
example:
function getData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("📦 Data from promise");
}, 1000);
});
}
getData()
.then(result => console.log(result))
.catch(error => console.error(error));
3)🧙 Async/Await (Introduced in ES8 - 2017)
What is it?
- Syntactic sugar over promises.
- Makes async code look synchronous.
- Works only inside async functions.
Improvement:
- Cleaner, more readable.
- Try/catch block makes error handling familiar.
example:
async function fetchData() {
try {
const result = await getData();
console.log(result);
} catch (error) {
console.error(error);
}
}
fetchData();
4)🧩 Top-level Await (Introduced in ES2022)
What is it?
Allows you to use await outside of an async function.
Mostly used in modules or top-level script files.
Improvement:
Useful for initialization scripts, loading configs, or data before app starts.
example:
const result = await fetch("https://api.example.com/data");
const data = await result.json();
console.log(data);
Must be in a module or a supported runtime like Deno or modern Node.js (with "type": "module").
5)🛠️ Newer Promise Features
not new paradigms, but powerful tools
5.1. Promise.all()
Run multiple promises in parallel and wait for all.
Promise.all([getUser(), getPosts(), getComments()])
.then(([user, posts, comments]) => console.log(user, posts, comments));
5.2. Promise.race()
Resolves/rejects as soon as any one of the promises does.
5.3. Promise.allSettled()
Waits for all promises to finish (regardless of success or failure).
📕 Summary
JavaScript Promise Concept Cheat Sheet
Concept | Meaning |
---|---|
Promise | "I’ll give it to you later" |
resolve | "Here you go!" |
reject | "Sorry, can't do it." |
.then() | "What to do after it’s done" |
.catch() | "What to do if it failed" |
async | Tells JS this function uses await inside |
await | "Wait here until I get the result" |
📊 Summary Table: Async Handling in JavaScript
Approach | Introduced In | Syntax Style | Pros | Cons | Example Keywords |
---|---|---|---|---|---|
Callbacks | Before ES6 | Function-based | Simple, works everywhere | Callback Hell, hard to manage | function(cb) {} |
Promises | ES6 (2015) | Chain-based | Cleaner than callbacks, chaining | Can still get nested |
.then() , .catch()
|
Async/Await | ES8 (2017) | Synchronous-like | Easy to read, debug, write | Only usable inside async funcs |
async , await
|
Top-level Await | ES2022 | Global await usage | Useful in modules | Not supported everywhere |
await (no func wrapper) |
Promise utilities | ES6+ | Combined use | Advanced control flow | Must understand promises well |
Promise.all() , race()
|
Want to Try It Yourself?
Here’s a simple test you can run in your browser console or in JSFiddle:
function makeTea() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("☕ Tea is ready!");
}, 1500);
});
}
async function startDay() {
console.log("Starting the day...");
const tea = await makeTea();
console.log(tea);
}
startDay();
💡 Pro Tip: Always choose the approach that keeps your code clean and readable. async/await
is your best friend in modern JavaScript!
i will post all promises methods in an interesting way in next blog soon . the above content is just to make you familiar about promises and async and await .
stay tuned !!
Happy Learning !!