Promises in JavaScript
When JavaScript performs an operation that takes some time, such as fetching data from a server, it does not want to wait and block the rest of the program. Instead, JavaScript can handle the operation asynchronously.
A Promise is an object that represents the eventual result of an asynchronous operation. In simple words, a Promise means "I don't have the result right now, but I will give you the result later."
Creating a Promise
We can create a Promise using the built-in Promise constructor:
const result = new Promise((resolve, reject) => {
const age = 10;
setTimeout(() => {
if (age >= 18) {
resolve("You are eligible to vote");
}
else {
reject("You are not eligible to vote");
}
}, 3000);
});
Here, Promise is a built-in JavaScript constructor, and new Promise() creates a new Promise object.
The function passed to new Promise() is called the executor function:
(resolve, reject) => {
// code
}
resolve and reject are parameters of this executor function. The Promise constructor provides functions as arguments for these parameters.
We call resolve() when the operation is successful and reject() when the operation fails.
resolve("You are eligible to vote");
means the operation was successful.
reject("You are not eligible to vote");
means the operation failed.
Promise States
A Promise has three possible states:
| State | Meaning |
|---|---|
| Pending | The operation is still in progress |
| Fulfilled | The operation completed successfully |
| Rejected | The operation failed |
In our example, when the Promise is created, it is initially pending.
After 3 seconds, the age is checked. Since the age is 10, the condition is false and reject() is called.
So the Promise changes from:
Pending
↓
Rejected
If the age were 18 or above, resolve() would be called instead:
Pending
↓
Fulfilled
Handling a Promise
After creating the Promise, we can use .then() to handle a successful result and .catch() to handle an error.
const result = new Promise((resolve, reject) => {
const age = 10;
setTimeout(() => {
if (age >= 18) {
resolve("You are eligible to vote");
}
else {
reject("You are not eligible to vote");
}
}, 3000);
})
.then((message) => {
console.log(message);
})
.catch((error) => {
console.log(error);
});
When resolve() is called, the value passed to it is received by .then():
resolve("You are eligible to vote");
The value "You are eligible to vote" becomes the argument passed to the .then() callback.
In:
.then((message) => {
console.log(message);
})
message is a parameter. It receives the value provided by the fulfilled Promise.
So the flow is:
resolve("You are eligible to vote")
↓
.then()
↓
message = "You are eligible to vote"
↓
console.log(message)
Similarly, when reject() is called:
reject("You are not eligible to vote");
the value is passed to .catch():
.catch((error) => {
console.log(error);
});
Here, error is a parameter that receives the rejected value.
The flow is:
reject("You are not eligible to vote")
↓
.catch()
↓
error = "You are not eligible to vote"
↓
console.log(error)
Why Promises Are Useful
Promises are especially useful for handling asynchronous operations. For example, an application might need to:
- Get a user
- Get the user's orders
- Get the details of an order
- Make a payment
When many asynchronous operations depend on each other, using callbacks can result in deeply nested code called callback hell.
Promises allow us to chain these operations using .then():
getUser()
.then(user => getOrders(user))
.then(orders => getOrderDetails(orders[0]))
.then(order => makePayment(order))
.catch(error => {
console.log(error);
});
Each .then() receives the result from the previous Promise and can return another Promise for the next operation.
This allows asynchronous operations to be written as a chain instead of deeply nested callbacks.
Conclusion
A Promise represents the eventual result of an asynchronous operation. It starts in a pending state and eventually becomes either fulfilled or rejected.
The important things to remember are:
-
Promiseis a built-in constructor. -
new Promise()creates a Promise object. - The function passed to
new Promise()is called the executor function. -
resolveandrejectare parameters that receive functions from the Promise constructor. -
resolve()is used when the operation succeeds. -
reject()is used when the operation fails. -
.then()handles a fulfilled Promise. -
.catch()handles a rejected Promise. - Promises can be chained to make asynchronous code easier to manage.
The basic idea is:
Promise
↓
Pending
↙ ↘
resolve reject
↓ ↓
Fulfilled Rejected
↓ ↓
.then() .catch()
Top comments (0)