JavaScript Promises Explained for Beginners
You write async code like this…
getUser(function(user) { getPosts(user.id, function(posts) { getComments(posts[0].id, function(comments) { console.log(comments); }); }); });
Looks confusing right? This is called callback hell
Now look at this:
getUser() .then(user => getPosts(user.id)) .then(posts => getComments(posts[0].id)) .then(comments => console.log(comments)) .catch(err => console.log(err));
Clean, Readable, Easy to debug
That’s why Promises exist
This is the Problem Promises Solve Before Promises:
Deep nested code (callback hell)
Hard to read and maintain
Error handling is messy
Debugging is painful
Example Problem Imagine:
Get user
Then get posts
Then get comments
With callbacks → nested pyramid With promises → straight flow
What is a Promise? A Promise is:
A value that will be available in the future
Imagine: Ordering food online:
Order placed → Pending, Delivered → Fulfilled, Cancelled → Rejected That’s exactly how Promises behave
Important Promise is: Not immediate, Asynchronous, Future-based value
Promise States - IMP
- Pending Initial state, Work is still happening
Example: API request is in progress
- Fulfilled Operation successful, Result is returned
Example: Data received from server
- Rejected Operation failed Error is returned
Example: Network error
Visual Flow Pending → Fulfilled → Rejected
Creating a Promise: Basic Syntax const promise = new Promise((resolve, reject) => { let success = true;
if (success) { resolve("Data received"); } else { reject("Error occurred"); } });
Explanation: new Promise() → create promise
resolve() → success
reject() → failure
Think Like This resolve → success path
reject → error path
Handling Success and Failure Using .then() and .catch() promise .then(result => { console.log(result); }) .catch(error => { console.log(error); });
Explanation .then() → runs when success happens
.catch() → runs when error happens
Mental Model Promise = “If this works → do this, else → do that”
Promise Lifecycle (Full Flow) Create → Pending → (resolve/reject) → then/catch
Flow Example fetchData() .then(data => processData(data)) .then(result => console.log(result)) .catch(err => console.log(err));
What happens here? First async task runs
When done → .then() runs
Next step runs
If error → .catch() handles
Promise Chaining (VERY IMPORTANT) Without chaining (bad) Nested again:
getUser(function(user) { getPosts(user.id, function(posts) { console.log(posts); }); });
With chaining (good) getUser() .then(user => getPosts(user.id)) .then(posts => console.log(posts)) .catch(err => console.log(err));
Why chaining is powerful? No nesting
Easy to read
Step-by-step logic
Better error handling
Rule Always return inside .then()
.then(user => { return getPosts(user.id); })
Callback vs Promise Callback Style login(user, function(data) { getProfile(data, function(profile) { console.log(profile); }); });
Promise Style login(user) .then(data => getProfile(data)) .then(profile => console.log(profile)) .catch(err => console.log(err));
Difference Callback Promise Nested Flat Hard to read Easy Multiple error handling Single catch Mental Model (Best Way to Remember) Promise = Pipeline Step 1 → Step 2 → Step 3 → Result
Each .then() = next step
Final Thought Promises don’t make async code faster.
They make it understandable
