In this tutorial, we will be looking at Promises in Javascript.
What is a Promise in short?
Promises are an alternative to callbacks for delivering the result of an asynchronous operation like making an HTTP call or reading and writing to a database. It allows users to perform asynchronous operations very effectively and seamlessly with its features.
Creation of a promise
In javascript, we use the new keyword to make a Promise. So, let’s create one.
const request = require("request");
const prom1 = new Promise((resolve, reject) => {
// Asynchronous operation
const url = "https://jsonplaceholder.typicode.com/posts";
request.get(url, (err, res, body) => {
const { statusCode } = res;
const json = JSON.parse(body);
if (err) {
return reject({statusCode, err});
}
return resolve({statusCode, json});
});
});
An asynchronous operation could be anything like a call to a database, writing/reading to the file system, making an HTTP request, and so on. In this case, we are making a GET request to an endpoint that responds with a status code and some dummy JSON data. If everything goes as expected we resolve the promise by calling the resolve function indicating that the call was a success. Whereas if anything goes wrong like let’s say the response isn’t what we expected or due to logical errors we can reject the promise by calling the reject function.
States of a promise
Once we have created a promise, it has three states.
- Pending state
- Fulfilled or Resolved state
- Rejected state
Let’s understand them one by one.
Pending state:- If a promise is pending, it means our asynchronous operation hasn’t finished yet and is still in progress.
Fulfilled or Resolved state:- If a promise is in the fulfilled or resolved state, that means our asynchronous operation has finished successfully.
Rejected state:- If a promise is in the rejected state, that means some failure occurred during operation.
Consume a promise
After the successful creation of a promise, the question arises of how can we handle/consume a promise. Well, we can handle a promise with its .then() & .catch()” methods. If a promise gets resolved then the .then() method captures the resolved value. Otherwise, if any error occurs .catch() block captures the error.
Let’s understand it with an example.
const request = require("request");
const prom1 = new Promise((resolve, reject) => {
// Asynchronous operation
const url = "https://jsonplaceholder.typicode.com/posts";
request.get(url, (err, res, body) => {
const { statusCode } = res;
const json = JSON.parse(body);
if (err) {
return reject({statusCode, err});
}
return resolve({statusCode, json});
});
});
prom1.then((res) => {
console.log(res);
}).catch((err) => console.log(err.message));
As discussed above, we created a promise that resolves if the server responds with a status-code 200 and some dummy JSON data.
Now that we have discussed Promise consumption, let’s talk about some of the promises static methods available in javascript.
Promise.all()
Promise.all(iterable) is a static promise method that takes an array of promises as an argument. Once all of them have been resolved, it returns a single promise that resolves to an array of the results of the input promises.
Let’s understand it with an example.
const request = require("request");
const prom1 = new Promise((resolve, reject) => {
// 1st Asynchronous operation
const url = "https://jsonplaceholder.typicode.com/posts/1";
request.get(url, (err, res, body) => {
const { statusCode } = res;
const data = JSON.parse(body);
if (err) {
return reject(err);
}
return resolve({ statusCode, data });
});
});
const prom2 = new Promise((resolve, reject) => {
// 2nd Asynchronous operation
const url = "https://reqres.in/api/users?page=1";
request.get(url, (err, res, body) => {
const { statusCode } = res;
const { data } = JSON.parse(body);
if (err) {
return reject(err);
}
return resolve({ statusCode, data: data[0] });
});
});
Promise.all([prom1, prom2])
.then(([prom1Res, prom2Res]) => {
console.log(prom1Res, prom2Res);
})
.catch((err) => {
console.log(err);
});
In the above example, we have two promises prom1 and prom2. We have passed both of the promises as an array to the Promise.all() method and both run concurrently. If all of them get successfully resolved the .then() method captures the array of their values. But if any of them get rejected then all fail and .catch() captures the error.
Have a look at our telegram crypto price bot tutorial where we have made use of promise.
The benefit of using Promise.all() is that we can make calls to two or more independent asynchronous codes or function calls concurrently and thus increase significantly improve the performance of our program.
NOTE: Promise.all waits for all the input promises to resolve and in case any one of the input promises rejects or throws an error it rejects immediately at that instant.
Promise.race()
Promise. race() is another static method that takes an array of promises and returns a promise.
You can think of the race() method as a race organizer, who asks the array of promises(participants) to race among themselves. If all goes well, whoever finishes first(resolves) wins but if any one of the participants gets injured(rejects) during the race, the race is terminated(rejected) at that instant.
Let’s understand it with an example.
const request = require("request");
const prom1 = new Promise((resolve, reject) => {
// Asynchronous operation
const url = "https://jsonplaceholder.typicode.com/posts";
request.get(url, (err, res, body) => {
const { statusCode } = res;
const data = JSON.parse(body);
if (err) {
return reject(err);
}
return resolve({ statusCode, data });
});
});
const prom2 = new Promise((resolve, reject) => {
// Asynchronous operation
const url = "https://reqres.in/api/users?page=1";
request.get(url, (err, res, body) => {
const { statusCode } = res;
const { data } = JSON.parse(body);
if (err) {
return reject(err);
}
return resolve({ statusCode, data });
});
});
Promise.race([prom1, prom2])
.then((result) => {
console.log(result);
})
.catch((err) => {
console.log(err);
});
In the above example, there are two promises prom1 and prom2 which we are assigning as an array to promise.race() method, whichever promise will resolve first we are storing their value in the res which in this example let’s suppose is prom1. Therefore the result of prom1 has logged into the console.
Promise.allSettled()
Promise.allSettled() also returns a single promise that resolves to result of an array of input promises similar to the Promise.all() method. However, unlike Promise.all() it doesn’t reject immediately upon any one of the input promises rejected but waits for all to finish.
Upon finish, it resolves to an array with the outcome of each one of the input promises(fulfilled in case of resolved otherwise rejected)
Let’s understand it with an example.
const request = require("request");
const prom1 = new Promise((resolve, reject) => {
// Asynchronous operation
const url = "https://jsonplaceholder.typicode.com/posts/5";
request.get(url, (err, res, body) => {
const data = JSON.parse(body);
if (err) {
return reject(err);
}
return resolve(data);
});
});
const prom2 = new Promise((resolve, reject) => {
// Asynchronous operation
const url = "https://reqres.in/api/users?page=2";
request.get(url, (err, res, body) => {
const { data } = JSON.parse(body);
if (err) {
return reject(err);
}
return resolve(data[0]);
});
});
Promise.allSettled([prom1, prom2])
.then(([response1, response2]) => {
console.log(response1, response2);
})
.catch((err) => {
console.log(err);
});
Advantage of using Promises over Callback in javascript
One of the important advantages of promises is that it handles asynchronous functions conveniently. It also saves us from callback hell, which improves our code readability and maintainability in the long run. Promises also make handling errors quite easy.
Conclusion
Walah! In this tutorial have successfully learned about promises. I tried to make this post simple and understandable. If you liked this post, please appreciate it in the comments. Also, feel free to raise your queries in the comment section.
One thought on “Promises in javascript for beginners”