Before we begin there are a few things to know about javascript:
JavaScript is single-threaded ----> One call stack -----> One thing executes at a time.
But in the real world, the apps/ websites we use talk to servers, they read files, server performs operations on data ----> These things take time ---->If JavaScript blocked while waiting, your UI would freeze.
Promises to come to our rescue.
A Promise is a value that represents the result of some time taking operation (async) — now, later, or never.
WHAT?
Promise = a container for a future result.
It can be in only have one of these 3 states:
pending → still waiting
fulfilled → succeeded (even of server responds with an error it is a fulfilled promise)
rejected → failed (Reject runs only when something breaks (like no internet, server failure, or DNS issue))
After it becomes fulfilled or rejected, it’s done and final ----> It cannot switch its state again.
Flashback
Before Promises, async (time-taking) code stacked inside itself like this:
getData(function(data) {
cleanData(function(cleaned) {
saveData(function() {
console.log("Finished");
});
});
});
Each step waits for the previous one, but the nesting keeps growing. Hard to read. Hard to manage errors. Try doing this for 45000 times you'll understand what I mean.
With Promises, the same code becomes flat and linear: most imp ----> READBLE
getData()
.then(cleanData)
.then(saveData)
.then(() => console.log("Finished"))
.catch(error => console.log("Something went wrong"));
Now how do we create a promise?
const myPromise = new Promise(function(resolve, reject) {
let ok = true;
if (ok) { resolve("Done");}
else {reject("Error");}
});
resolve("Done")→ Promise becomes fulfilled ,reject("Error")→ Promise becomes rejected
Onlyresolveorrejectcan settle the promise.
Using a Promise:
herPromise
.then(function(result) {
console.log(result);
})
.catch(function(error) {
console.log(error);
});
.then()runs if it was fulfilled.catch()runs if it was rejected
Both .then() and .catch() return a new Promise. That’s why we can keep chaining them.
HEART of promises
Every .then() gives you a new Promise.
fetch("/her-api")
.then(res => res.json())
.then(data => show(data))
.catch(err => showError(err));
NOW...........read carefully:
Each step waits for the previous one.
Inside .then():
If you return a normal value → it goes to the next
.then()If you return a Promise → it waits for that Promise
If you throw an error → it skips everything and goes to
.catch()
NOTE: Errors automatically move down the chain until they find a .catch().
something about fetch()
fetch() only rejects ----> when the network fails (no internet, DNS issue, blocked request).
It does not reject for 404 or 500 errors. So this still counts as “success” to fetch:
WHAT PROMISES DO NOT DO:
Promises are not workers. They don’t do the work.
They do not create threads.
They do not make JavaScript parallel.
They do not run in background magically.
They do not block execution.
They only manage the timing and flow of time taking operations
The real async work is done by:
Browser APIs (like
fetch, timers)Node APIs (like file system, network)
The event loop (the system that decides what runs next)
A Promise is just a coordination tool. It says: “When this task finishes, do this then do this, then do this......”
I have created a visual playground for you to understand go and play it here:
https://chaipromise.netlify.app/.
Thanks for reading.