Promises - JavaScript Concepts Simplified
Tags: javascript, beginners, programming, webdev
Published: 2022-02-12 14:58:03

## What is a Promise?

By definition, a promise is a declaration that one will do something or that a particular thing will happen. In the programming world, a promise is an object that represents the eventual completion (or failure) of an asynchronous operation. 

## States

A promise can have the following states.

1. Pending (Initial State, neither fulfilled nor rejected)
2. Fulfilled (The operation was a success)
3. Rejected (The operation was a failure)

A pending promise can either be fulfilled or rejected. We can attach handler methods to handle the events of promises getting `fulfilled` and `rejected`. We can use the then method in promises to attach these handlers.

```
promise.then(handleSuccess, handleRejection)
```

We have attached two handler methods to the above promise. Now, if the promise gets fulfilled, `handleSuccess` will be called and if it gets rejected, the `handleRejection` method will be called.

When a promise is not in the pending state, we say the promise is settled. Please keep in mind that being settled is merely a linguistic convenience, not a state.

## Methods

In addition, promise objects have multiple methods that can be really useful when handling promises.

## 1. Promise.all()

Input - An iterable of promises
Output - A single promise that resolves into an array of the results of the input promises

This method is useful when you have more than one promise and you want to do something only when all the operations are completed successfully. `Promise.all()` will reject immediately upon any of the input promises rejecting. For example, if you want to make multiple API calls and the code relies on all of them to be successful, you can use `Promise.all()`.

```
const firstPromise = new Promise((resolve, reject) => {
  setTimeout(resolve, 300, "First Promise");
});

const secondPromise = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, "Second Promise");
});

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

const rejectedPromise = Promise.reject("EVERYBODY STAY CALM. STAY F***ING CALM. I WAS REJECTED");

//Promise.all() method
Promise.all([firstPromise, secondPromise, thirdPromise])
  .then((results) => {
    console.log("All the promises were fulfilled here - ", results);
  })
  .catch((error) => {
    console.error("Error: ", error);
  });

//Promise.all() method with a rejected promise
Promise.all([firstPromise, rejectedPromise, thirdPromise])
  .then((results) => {
    console.log("All the promises were fulfilled");
    console.log("Response from all method - ", results);
  })
  .catch((error) => {
    console.error("Error: ", error);
  });
```

Output

```
Error:  EVERYBODY STAY CALM. STAY F***ING CALM. I WAS REJECTED
All the promises were fulfilled here -  [ 'First Promise', 'Second Promise', 'Third Promise' ]
```

## 2. Promise.allSettled()

Input - An iterable of promises
Output - A single promise that resolves into an array of the results of the input promises

We can use this method when the tasks are dependent on each other and you want to know all the results of all the promises regardless of the result of each promise.

```
//Promise.allSettled() method with a rejected promise
Promise.allSettled([firstPromise, rejectedPromise, thirdPromise])
  .then((results) => {
    console.log("I don't care if all the results are fulfilled or not");
    console.log("Response from allSettled method - ", results);
  })
  .catch((error) => {
    console.error("Error: ", error);
  });
```

You can clearly see the difference between the `all` and `allSettled` methods. The `all` method wants all the promises to be fulfilled while `allSettled` method only wants the promises to be `settled` (regardless of `fulfilled` or `rejected`)

```
I don't care if all the results are fulfilled or not
Response from allSettled method -  [
  { status: 'fulfilled', value: 'First Promise' },
  {
    status: 'rejected',
    reason: 'EVERYBODY STAY CALM. STAY F***ING CALM. I WAS REJECTED'
  },
  { status: 'fulfilled', value: 'Third Promise' }
]
```

## 3. Promise.any()

Input - An iterable of promises
Output - A single promise that resolves as soon as any of the promises in the iterable fulfils, with the value of the fulfilled promise

If none of the promises gets fulfilled, then the returned promise is rejected with an `AggregateError`.

```
const firstPromise = new Promise((resolve, reject) => {
  setTimeout(resolve, 300, "First Promise");
});

const secondPromise = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, "Second Promise");
});

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

const rejectedPromise = Promise.reject(
  "EVERYBODY STAY CALM. STAY F***ING CALM. I WAS REJECTED"
);

//Promise.any() Method
Promise.any([firstPromise, secondPromise])
  .then((fasterPromise) => {
    console.log("Response from any method with no rejections - ", fasterPromise);
  })
  .catch((error) => {
    console.error("Error: ", error);
  });

//Promise.any() Method with rejections
Promise.any([rejectedPromise, rejectedPromise])
  .then((fasterPromise) => {
    console.log("Response from any method with rejections - ", fasterPromise);
  })
  .catch((error) => {
    console.error("Error: ", error);
  });


//Promise.any() Method
Promise.any([firstPromise, secondPromise]).then((fasterPromise) => {
  console.log("Response from any method - ", fasterPromise);
});
```

Output

```
Error:  [AggregateError: All promises were rejected]
Response from any method with no rejections -  Second Promise
```

## 4. Promise.race()

Input - An iterable of promises
Output - A promise that `fulfils` or `rejects` as soon as one of the promises in an iterable fulfils or rejects, with the value or reason from that promise

```
const firstPromise = new Promise((resolve, reject) => {
  setTimeout(resolve, 300, "First Promise");
});

const secondPromise = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, "Second Promise");
});

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

const rejectedPromise = Promise.reject(
  "EVERYBODY STAY CALM. STAY F***ING CALM. I WAS REJECTED"
);

//Promise.race() Method
Promise.race([firstPromise, secondPromise])
  .then((fasterPromise) => {
    console.log(
      "Response from race method with no rejections - ",
      fasterPromise
    );
  })
  .catch((error) => {
    console.error("Error: ", error);
  });

//Promise.race() Method with rejections
Promise.race([secondPromise, rejectedPromise])
  .then((fasterPromise) => {
    console.log("Response from race method with rejections - ", fasterPromise);
  })
  .catch((error) => {
    console.error("Error: ", error);
  });
```
As the name of the method suggests, we have a race here. It does not matter whether the promises are `fulfilled` or `rejected`. The `race` method returns the fastest settled promise.

Output

```
Error:  EVERYBODY STAY CALM. STAY F***ING CALM. I WAS REJECTED
Response from race method with no rejections -  Second Promise
```

## 5. Promise.reject() and Promise.resolve()

You are already familiar with the reject method since I’ve used it in earlier examples. Basically, we use the reject method to reject a promise.

In addition, we have the resolve method which returns a promise that is resolved with the given value, or the promise passed as value, if the value was a promise object. Resolved is not to be confused with fulfilled. Please read [this StackOverflow answer](https://stackoverflow.com/questions/35398365/js-promises-fulfill-vs-resolve) to learn more about it.

## Fates

Promises also have two mutually exclusive fates, resolved and unresolved.

1. If we try to resolve or reject a promise and it has no effect, we say the promise is resolved.
2. If we try to resolve or reject a promise and it has an effect, we say the promise is unresolved.

## Conclusion

To sum things up, we use promises to handle asynchronous operations in JavaScript. Especially, when there are multiple asynchronous operations running, it would be a nightmare to handle them if you don't know about promises.

I hope you learned something valuable from Today's article. If you liked it, drop a like and follow me so that you don't miss the upcoming articles. And as always, stay safe guys 😷