Promises - JavaScript
Source: Dev.to
Introduction
JavaScript is synchronous by default, meaning code executes line‑by‑line and each statement waits for the previous one to finish.
Operations such as API calls can take time; if JavaScript waited for them synchronously, the whole program would pause and become unresponsive.
To avoid blocking execution, JavaScript supports asynchronous programming.
What Is a Promise?
A Promise is an object that represents the eventual completion (or failure) of an asynchronous operation.
Promises allow JavaScript to continue executing other code while waiting for long‑running tasks to finish.
Promise States
- Pending – the operation is still running.
- Fulfilled – the operation completed successfully.
- Rejected – the operation failed.
Why Promises?
Before promises, asynchronous tasks were handled with callback functions. A callback is passed as an argument to another function and executed later, usually after an asynchronous task completes.
When multiple asynchronous operations depend on each other, callbacks become deeply nested, leading to callback hell.
Callback Hell Example
function analyse(callback) {
setTimeout(() => {
console.log("done analysis");
callback();
}, 2000);
}
function design(callback) {
setTimeout(() => {
console.log("done design");
callback();
}, 1000);
}
function develop(callback) {
setTimeout(() => {
console.log("done development");
callback();
}, 3000);
}
function test(callback) {
setTimeout(() => {
console.log("done testing");
callback();
}, 2000);
}
function deploy(callback) {
setTimeout(() => {
console.log("done deployment");
callback();
}, 1000);
}
// Executed in order – results in callback hell
analyse(() => {
design(() => {
develop(() => {
test(() => {
deploy(() => {
console.log("SDLC completed");
});
});
});
});
});
Problems with Callback Hell
- Code becomes difficult to read.
- Hard to maintain.
- Error handling is complicated.
- Debugging is challenging.
Solving Callback Hell with Promises
Promises flatten the asynchronous flow, making the code easier to read and maintain.
Promise‑Based Implementation
function analyse() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("done analysis");
resolve();
}, 2000);
});
}
function design() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("done design");
resolve();
}, 1000);
});
}
function develop() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("done development");
resolve();
}, 3000);
});
}
function test() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("done testing");
resolve();
}, 2000);
});
}
function deploy() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("done deployment");
resolve();
}, 1000);
});
}
function sdlc() {
analyse()
.then(() => design())
.then(() => develop())
.then(() => test())
.then(() => deploy())
.then(() => console.log("SDLC Completed"))
.catch(err => console.error("Error:", err));
}
sdlc();
Output
Running the above script produces the following console output (with the respective delays):
done analysis
done design
done development
done testing
done deployment
SDLC Completed