Promises in javascript for beginners

promises in javascript for beginners

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));
Promise resolved response in javascript
Resolved response

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.

Promise.all resolves demonstration
Promise.all resolves
Promise.all rejects demonstration
Promise.all rejects

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.

Promise all output
Promise all output

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.

Promise.race resolves demonstration
Promise.race resolves
Promise.race rejects demonstration
Promise.race rejects

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);
  });
promise race output
Promise.race() output

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)

Promise.allSettled resolves demonstration
Promise.allSettled resolves

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);
  });
Promise allSettled result
Promise.allSettled output

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

Leave a Reply

Back To Top