hey its me shivam
todays topic of blog is callback and promise
so lets start without wasting any time lets move to actual work
soooo the story starts from two things
- async operation
- sync operation
before understanding callback and promise we first need to understand why async programming even exist
because if u directly jump into promise and callback then trust me u will memorize it
not understand it ðŸ˜
Sync Operation
so in this the code run line by line yes this is the simplest explanation of sync operation
for example
console.log("Start");
console.log("Task 1");
console.log("Task 2");
console.log("End");
so the output will be
Start
Task 1
Task 2
End
and execution might look like this
Start
↓
Task 1
↓
Task 2
↓
End
JavaScript waits for one task to finish before moving to the next.
simple
clean
straight
like a good boy following rules ðŸ˜
The Problem With Synchronous Code
now the problem is imagine a heavy task
like this
console.log("Start");
for (let i = 0; i < 1e9; i++) {}
console.log("Done");
JavaScript is kinda blocked after start because the loop is kinda like infinite
so at this time:
- UI might freeze
- button don't work
- server cannot handle other request
this is called blocking code
and this is dangerous in backend too
because one blocked request can slow other users request too
and users nowadays have patience level of goldfish 💀
Async Operation
now comes the async operation in this
in this the code start executing line by line and whenever the heavy code like this is seen then it is executed but rather than standing there as a dumb
the JavaScript will run another task after that line
and when the execution of heavy task is done then the output is thrown out
example
console.log("Start");
setTimeout(() => {
console.log("Timer Finished");
}, 2000);
console.log("End");
output
Start
End
Timer Finished
Execution flow:
Start
↓
setTimeout registered
↓
End
↓ (after 2 sec)
Timer Finished
so basically sync code is like good boy walking straight forward
and async code is like:
"i will not wait i busy (he not) call me when the task is done till then i will execute another baddies"
ðŸ˜
Why Async Code Exists in Node.js
Node.js is built around:
- non-blocking architecture
- asynchronous execution
- handling multiple request together
Imagine if every API request blocked the server.
then server would literally die handling large traffic
instead Node.js says:
"start the task and call me later when done"
that is the whole philosophy behind async programming
now i will explain callback and promise
i know i know it was lengthy but it was necessary guy i cannot do anything
sooooooo..........
let understand
- callback
- promise
What is Callback?
callback is a function which is passed as a parameter into another function so that it can call it later
yes this what callback is
this how it look's like
function greet(name) {
console.log("Hello " + name);
}
function processUser(callback) {
const name = "Shivam";
callback(name);
}
processUser(greet);
Output:
Hello Shivam
What Happened Here?
processUser(greet);
We passed the greet function as an argument.
Inside:
callback(name);
The callback function gets executed later.
that is literally callback
a function waiting for another function to call it later
like me waiting for motivation to study ðŸ˜
Callback Execution Chain
Start Async Task
↓
Continue Other Code
↓
Task Completes Later
↓
Callback Added To Queue
↓
Event Loop Executes Callback
this is where Node.js event loop also enters into picture
because callback don't magically execute
event loop handles that execution
but event loop itself is another huge topic ðŸ˜
Callback Hell
while learning about callback i got to know callback hell
like this not seen much nowadays but it exist
so what is callback hell
imagine multiple task are depended on each other
example
- Get user
- Fetch posts
- Fetch comments
- Save logs
Using callbacks:
getUser(id, (user) => {
getPosts(user.id, (posts) => {
getComments(posts[0].id, (comments) => {
saveData(comments, () => {
console.log("Done");
});
});
});
});
The Callback Hell Problem
This structure creates:
- Deep nesting
- Poor readability
- Difficult debugging
- Complex maintenance
This is famously called:
Callback Hell
or
Pyramid of Doom
because code shifts endlessly to the right.
bro this code literally starts looking like staircase ðŸ˜
So To Solve This Problem We Got Promise
so what is promise
promise is a special object used to handle asynchronous operation
it represent the eventual result of an operation that may:
- complete
- fail
in the future
it can be:
- API request
- DB calls
- file reading
- network communication
etc
A promise acts as a placeholder for a value that is not available immediately but will be available later.
Why Promises Are Needed?
JavaScript performs many operations asynchronously, such as:
- API requests
- Database queries
- File reading
- Timers
- Network communication
These operations take time to complete.
Instead of blocking the execution of the program while waiting, JavaScript continues executing other code and uses promises to handle the result later.
Promises basically made async code cleaner and more manageable
because callback hell was becoming a horror movie 💀
States of a Promise
A promise can exist in one of three states:
| State | Meaning |
|---|---|
| Pending | Initial state; operation is still running |
| Fulfilled | Operation completed successfully |
| Rejected | Operation failed |
State Transition
Pending
↓
Fulfilled OR Rejected
Once fulfilled or rejected, the promise becomes permanently settled and its state cannot change again.
Promise Resolution
A promise produces a result through:
resolve()
Used when the operation succeeds.
reject()
Used when the operation fails.
Example of Promise
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("User data");
}, 2000);
});
}
the promise return an object which will be having:
- state
- returned output(data)
so to handle that we use .then().catch() syntax
which looks like this
fetchData()
.then((data) => {
console.log(data);
})
.catch((err) => {
console.log(err);
});
Promise Lifecycle Flow
Promise Created
↓
Pending
↓ ↓
Resolved Rejected
↓ ↓
.then() .catch()
Promise Chaining
but here there is another problem like callback hell
that is promise chain
so in this the promise is chained with .then() function
like this
fetchUser()
.then((user) => {
return fetchPosts(user.id);
})
.then((posts) => {
return fetchComments(posts[0].id);
})
.then((comments) => {
console.log(comments);
})
.catch((err) => {
console.log(err);
});
this is still way cleaner than callback hell
because now code moves downward instead of becoming pyramid
which means:
- readability improve
- debugging improve
- maintenance improve
and developer cry little less ðŸ˜
Important Clarification
Promises do NOT make code asynchronous.
Node.js async APIs already work asynchronously.
Promises simply provide:
- Better structure
- Better readability
- Better async management
this is very important thing
many beginner think promises create async behavior
NO
they just manage async behavior better
under the pant thing
ðŸ˜
Async/Await Comes from Promises
Modern JavaScript uses:
async/await
But internally:
async/await is built on top of promises.
Example:
async function readFile() {
try {
const data = await fs.readFile("demo.txt", "utf-8");
console.log(data);
} catch (err) {
console.log(err);
}
}
This looks synchronous but still works asynchronously underneath.
and this is why async/await became so popular
because human brain likes readable code ðŸ˜
Callback vs Promise Readability
Callback
getUser(id, (user) => {
getPosts(user.id, (posts) => {
getComments(posts[0].id, (comments) => {
console.log(comments);
});
});
});
Promise
fetchUser()
.then((user) => fetchPosts(user.id))
.then((posts) => fetchComments(posts[0].id))
.then((comments) => console.log(comments))
.catch((err) => console.log(err));
Promise version clearly looks cleaner
less nesting
less chaos
less depression 💀
The Evolution of Async JavaScript
Synchronous Code
↓
Callbacks
↓
Promises
↓
Async/Await
Final Understanding
Callbacks introduced asynchronous programming in Node.js by allowing functions to execute later after tasks completed.
But nested callbacks created readability and maintenance problems.
Promises improved async programming by providing:
- Cleaner structure
- Easier chaining
- Better error handling
- Improved readability
The core idea behind all of them remains the same:
Start task
↓
Continue execution
↓
Handle result later
That non-blocking philosophy is what makes Node.js powerful for modern backend applications.
in the end
so in the end this is my bye
good night if u are reading this at night because i am writing this at night
and if u understood callback and promise after reading this
then my mission successful ðŸ˜
bye bye
Top comments (0)