8-ES6++: Promises
Tags: javascript, es6, esnext
Published: 2022-11-19 04:53:56

---
title: 8-ES6++: Promises
published: true
description: 
series: es6++
tags: javascript, es6, esnext
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/321vl8g3ovxuz6nm0mgn.png
# Use a ratio of 100:42 for best results.
# published_at: 2022-10-25 09:51 +0000
---

## Promises In JavaScript

In **ES6** we have a new way to work with asynchronous code, which is called `promises`. Promises are a new way to handle asynchronous code in JavaScript. They are a new way to write asynchronous code that is easier to read and write.

If you don't know what is `asynchronous` code, let me tell you what is it.

Asynchronous code is code that doesn't run in order. For example, if you have a function that makes an HTTP request to get some data, that function will take some time to get the data, so the code after that function will run before the function finishes, that is `asynchronous code`.

Usually it is handled using `callbacks`, but `promises` are a new way to handle asynchronous code.

If you are not familiar with `callbacks`, let me tell you what is it.

`Callbacks` are functions that are passed to another function as a parameter, and that function will call the callback function when it finishes, in our previous example we'll pass a callback function to the function that makes the HTTP request, and that function will call the callback function when it finishes.

Now back to our topic, `promises`.

Promises are defined with `new Promise()`, and it takes a function as a parameter, that function takes two parameters, `resolve` and `reject`, and we use them to resolve or reject the promise.

Let's see an example:

```js
const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Hello World");
  }, 1000);
});

promise.then((data) => {
  console.log(data); // Hello World
});
```

So what does `resolve` do? It resolves the promise `A.K.A` it marks it as `completed successfully`, and what does `reject` do? It rejects the promise `A.K.A` it marks it as `failed`.

In the example above, we defined a promise that will resolve after 1 second, and then we used `then` to get the data from the promise.

We can also use `catch` to handle errors, where the `failed` promise will be handled.

```js

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("Error");
  }, 1000);
});

promise.catch((error) => {
  console.log(error); // Error
});
```

So we can conclude that the promise receives a callback function which receives two parameters, `resolve` and `reject`, and the promise object is returned with couple of methods (so far), the `then` method to handle the resolved `success` promise, and the `catch` method to handle the rejected `failed` promise.

## Chaining Promises

We can chain promises, and that is very useful when we have multiple asynchronous operations that depend on each other.

For example, Let's say we have a function to get the user data, and another function to get the user posts, and we want to get the user data first, then get the user posts, and then log the user data and the user posts.

```js
const getUserData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        id: 155,
        name: "Hasan",
        age: 20,
      });
    }, 1000);
  });
};

const getUserPosts = (userId) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(["Post 1", "Post 2", "Post 3"]);
    }, 1000);
  });
};

getUserData()
  .then((user) {
    getUserPosts(user.id).then(posts => {
      console.log(user, posts);
    });
  });
```

So we can see that we have two promises, the first one is to get the user data, and the second one is to get the user posts, and we want to get the user data first, then get the user posts, and then log the user data and the user posts.

In brief, we can use `then` to get the user data, and then use `then` again to get the user posts, and then log the user data and the user posts.

But there is a problem, what if we have more than two promises, and we want to get the user data first, then get the user posts, then get the user friends, and then get the user friends posts, and then log the user data and the user posts and the user friends and the user friends posts?

Here comes the magical solution, the `async` and `await` operators.

## Async and Await

The `async` and `await` operators are used to handle promises in a more readable way, and they are used with `promises`.

How they work? Let's see an example:

```js
const getUserData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        id: 155,
        name: "Hasan",
        age: 20,
      });
    }, 1000);
  });
};

const getUserPosts = (userId) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(["Post 1", "Post 2", "Post 3"]);
    }, 1000);
  });
};

const getUserDataAndPosts = async () => {
  const user = await getUserData();
  const posts = await getUserPosts(user.id);
  console.log(user, posts);
};

getUserDataAndPosts();
```

So we can see that we have two promises, the first one is to get the user data, and the second one is to get the user posts, and we want to get the user data first, then get the user posts, and then log the user data and the user posts.

Let's split the code into two parts, the first part is the `async` function, and the second part is the `await` operators.

The code before `getUserDataAndPosts` is the same as the previous example, so we'll cover starting from `const getUserDataAndPosts = async () => {`.

The `async` keyword is used to define an `async` function, and the `await` keyword is used to wait for a promise to resolve, and then assign the resolved value to a variable.

So we can see that we have two promises, the first one is to get the user data, and the second one is to get the user posts, and we want to get the user data first, then get the user posts, and then log the user data and the user posts.

That where `await` comes in, we use `await` to wait for the promise to resolve, and then assign the resolved value to a variable.

We can't use `await` outside of an `async` function, so we have to define an `async` function, and then use `await` inside it.

## Try and Catch

What if the promise fails? let's see how to handle the `rejected` promise.

```js
const getUserData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject("Error");
    }, 1000);
  });
};

const getUserPosts = (userId) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(["Post 1", "Post 2", "Post 3"]);
    }, 1000);
  });
};

const getUserDataAndPosts = async () => {
  try {
    const user = await getUserData();
    const posts = await getUserPosts(user.id);
    console.log(user, posts);
  } catch (error) {
    console.log(error);
  }
};

getUserDataAndPosts();
```

In the above example, we have rejected the promise in the first function which retrieves the user data, in that sense, the code will stop executing and will go to the `catch` block, and the error will be logged, thus the `getUserPosts` function will not be executed.

But if the opposite happened, the `getUserData` function is resolved successfully, and the `getUserPosts` function is rejected, it will execute the first function successfully but it will jump to the `catch` block and log the error because the `getUserPosts` function is rejected.

## Promise.all

Now let's have another scenario, we have multiple promises but we need to wait for all of them to resolve, and then do something with the resolved values.

For example, let's say we have a function to get the user data, and another function to get the user posts, and we want to get the user data and the user posts at the same time, and then log the user data and the user posts.

Here we can use `Promise.all` to wait for all promises to resolve, and then do something with the resolved values.

```js
const getUserData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        id: 155,
        name: "Hasan",
        age: 20,
      });
    }, 1000);
  });
};

const getUserPosts = (userId) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(["Post 1", "Post 2", "Post 3"]);
    }, 1000);
  });
};

const getUserDataAndPosts = async () => {
  const [user, posts] = await Promise.all([getUserData(), getUserPosts()]);
  console.log(user, posts);
};

getUserDataAndPosts();
```

What we did here is we called `Promise.all` method which receives an array of `Promises`, it will wait until all promises are resolved successfully then it will return an array of the resolved values.

But what if one of the promises is rejected? let's see how to handle the `rejected` promise.

```js
const getUserData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject("Error");
    }, 1000);
  });
};

const getUserPosts = (userId) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(["Post 1", "Post 2", "Post 3"]);
    }, 1000);
  });
};


const getUserDataAndPosts = async () => {
  try {
    const [user, posts] = await Promise.all([getUserData(), getUserPosts()]);
    console.log(user, posts);
  } catch (error) {
    console.log(error);
  }
};

getUserDataAndPosts();
```

The question here, would the `Promise.all` continue trying to resolve the other promises if one of them is rejected? the answer is no, it will stop trying to resolve the other promises and will jump to the `catch` block.

## Finally Block

The `finally` block is called in both scenarios, whether the promise is resolved `Successfully done` or rejected `Failed to resolve`.

Let's see how to use it first with the `then` and `catch` methods.

```js
const getUserData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        id: 155,
        name: "Hasan",
        age: 20,
      });
    }, 1000);
  });
};

const getUserPosts = (userId) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(["Post 1", "Post 2", "Post 3"]);
    }, 1000);
  });
};

const getUserDataAndPosts = () => {
  getUserData()
    .then((user) => {
      return getUserPosts(user.id);
    })
    .then((posts) => {
      console.log(posts);
    })
    .catch((error) => {
      console.log(error);
    })
    .finally(() => {
      console.log("Done");
    });
};

getUserDataAndPosts();
```

In the above example there will be two logs, the first one is the user posts which is called from `then` method, and the second one is `Done` which is called from `finally` method.

Now let's see how to use it with `async` and `await`.

```js
const getUserData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        id: 155,
        name: "Hasan",
        age: 20,
      });
    }, 1000);
  });
};

const getUserPosts = (userId) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject('Error');
    }, 1000);
  });
};

const getUserDataAndPosts = async () => {
  try {
    const [user, posts] = await Promise.all([getUserData(), getUserPosts()]);
    console.log('Successfully Completed');
    console.log(user, posts);
  } catch (error) {
    console.log('ERROR');
    console.log(error);
  } finally {
    console.log("Done");
  }
};

getUserDataAndPosts();
```

Here will be also two logs, the first one will be from the `catch` block because the first promise is rejected, and the second one will be from the `finally` block.

## Promise.allSettled

The `Promise.allSettled` method is similar to the `Promise.all` method, but it will wait for all promises to be settled, whether they are resolved or rejected, and then it will return an array of objects, each object will have the status of the promise, and the value or the error.

Let's see how to use it.

```js
const getUserData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        id: 155,
        name: "Hasan",
        age: 20,
      });
    }, 1000);
  });
};

const getUserPosts = (userId) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject("Error");
    }, 1000);
  });
};

const getUserDataAndPosts = async () => {
  const results = await Promise.allSettled([
    getUserData(),
    getUserPosts(),
  ]);
  console.log(results);
};

getUserDataAndPosts();
```

The result will be an array of objects, each object will have the status of the promise, and the value or the error.

```json
[
  {    
    "status": "fulfilled",
    "value": {
      "id": 155,
      "name": "Hasan",
      "age": 20
    }
  },
  {
    "status": "rejected",
    "reason": "Error"
  }
]
```

## Promise.any

The `Promise.any` method is similar to the `Promise.all` method, but it will wait for **first** promise to be resolved, and then it will return the resolved value.

Let's see how to use it.

```js
const getUserData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        id: 155,
        name: "Hasan",
        age: 20,
      });
    }, 1000);
  });
};

const getUserPosts = (userId) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject("Error");
    }, 1000);
  });
};

const getUserDataAndPosts = async () => {
  const user = await Promise.any([getUserData(), getUserPosts()]);
  console.log(user);
};

getUserDataAndPosts();
```

The result will be the resolved value.

```json
{
  "id": 155,
  "name": "Hasan",
  "age": 20
}
```

But what if the first promise is rejected and the second one is resolved, will it return the resolved value or the rejected error? the answer is the `resolved value`.

```js
const getUserData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject("Error");
    }, 1000);
  });
};

const getUserPosts = (userId) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(["Post 1", "Post 2", "Post 3"]);
    }, 1000);
  });
};

const getUserDataAndPosts = async () => {
  const posts = await Promise.any([getUserData(), getUserPosts()]);
  console.log(posts);
};

getUserDataAndPosts();
```

Outputs:

```json
["Post 1", "Post 2", "Post 3"]
```

So `Promise.all` waits for all resolved promises but `Promise.any` waits for the first resolved one.

## Promise.race

The `Promise.race` is from its name, will wait for the first resolved promise and resolve it regardless it is order in the array.

Let's see how to use it.

```js
const getUserData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        id: 155,
        name: "Hasan",
        age: 20,
      });
    }, 2000);
  });
};

const getUserPosts = (userId) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(["Post 1", "Post 2", "Post 3"]);
    }, 1000);
  });
};


const getUserDataAndPosts = async () => {
  const posts = await Promise.any([getUserData(), getUserPosts()]);
  console.log(posts);
};

getUserDataAndPosts();
```

As we can see, the `getUserData` will be delay with 2 seconds, but the `getUserPosts` will be delay with 1 second, but the result will be the `getUserPosts` because it is the first resolved promise.

Outputs:

```json
["Post 1", "Post 2", "Post 3"]
```

## A note before we conclude

Promises in Javascript has another name in other programming languages called `Futures`, they are more or less the same concept, just wanted to let you know that because you might hear this name in other programming languages.

## 🎨 Conclusion

In this article, we learned the concept behind `Promises` and why and how it is useful in our applications

We also learned about the `Promise.all`, `Promise.allSettled`, `Promise.any`, and `Promise.race` methods, and how to use them.

## ☕♨️ Buy me a Coffee ♨️☕

If you enjoy my articles and see it useful to you, you may [buy me a coffee](https://www.paypal.com/paypalme/hassanzohdy), it will help me to keep going and keep creating more content.

## 😍 Join our community

Join our community on [Discord](https://discord.gg/pb2vmdfhGf) to get help and support (Node Js 2023 Channel).

## 📚 Bonus Content 📚

You may have a look at these articles, it will definitely boost your knowledge and productivity.

General Topics

* [Event Driven Architecture: A Practical Guide in Javascript](https://dev.to/hassanzohdy/event-driven-architecture-the-best-paradigm-that-i-love-to-work-with-in-javascript-and-node-js-1gnk)
* [Best Practices For Case Styles: Camel, Pascal, Snake, and Kebab Case In Node And Javascript](https://dev.to/hassanzohdy/best-practices-for-case-styles-camel-pascal-snake-and-kebab-case-in-node-and-javascript-55oi)
* [After 6 years of practicing MongoDB, Here are my thoughts on MongoDB vs MySQL
](https://dev.to/hassanzohdy/after-6-years-of-practicing-mongodb-here-are-my-thoughts-on-mongodb-vs-mysql-574b)

Packages & Libraries

* [Collections: Your ultimate Javascript Arrays Manager](https://dev.to/hassanzohdy/collections-your-ultimate-javascript-array-handler-3o15)
* [Supportive Is: an elegant utility to check types of values in JavaScript](https://dev.to/hassanzohdy/supportive-is-an-elegant-utility-to-check-types-of-values-in-javascript-1b3e)
* [Localization: An agnostic i18n package to manage localization in your project](https://dev.to/hassanzohdy/mongez-localization-the-simplest-way-to-translate-your-website-regardless-your-favorite-framework-4gi3)

 React Js Packages

* [useFetcher: easiest way to fetch data in React Js](https://dev.to/hassanzohdy/usefetcher-the-easiest-way-to-fetch-data-in-react-45o9)

Courses (Articles)

* [Node Js 2023 Course: Node With Typescript, The Ultimate Guide](https://dev.to/hassanzohdy/nodejs-course-2023-introduction-to-nodejs-3n4e)
* [React Js: Let"s Create File Manager With React Js and Node Js](https://dev.to/hassanzohdy/lets-create-a-file-manager-from-scratch-with-react-and-typescript-chapter-i-a-good-way-to-expand-your-experience-5g4k)