What does Javascript Promise us for 2020?
Tags: javascript, node, webdev, beginners
Published: 2019-11-03 16:56:14

---
title: What does Javascript Promise us for 2020?
published: true
description: Promises are available since ES2015 to simplify the handling of asynchronous operations. Promises have two well-known combinators; `all` and `race`. Both of them are useful, but they don't cover all the use-cases. What if we want to wait for all the Promises even if some of them go to error or only the first successful operation is essential? I'll show you the new Promise combinators that will help you give the answers to these questions.
tags: javascript, node, webdev, beginner
cover_image: https://thepracticaldev.s3.amazonaws.com/i/i8naq1bb8f0hiqei36or.jpg
series: Javascript Next
---

Promises are available since ES2015 to simplify the handling of asynchronous operations. Promises have two well-known combinators: `all` and `race`. Both of them are useful, but they don't cover all the use-cases. What if we want to wait for all the Promises even if some of them go to error or only the first successful operation is essential? I'll show you the new Promise combinators that will help you give the answers to these questions.

First, we will look at the combinators that we already have and then look at two upcoming ones.

### Promise.all ([docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all))

The `all` combinator takes multiple promises (an iterator, in most cases an array) and returns a single promise that resolves when all the promises are completed, or the iterator doesn't contain any element. There is no ordering of the given promises; they execute in parallel. However, the return value order of each input promise will be the same as were in the input. The returned promise will contain the value of the inputs in an array.

```javascript
const first = Promise.resolve('Batman');
const second = Promise.resolve('Joker');

Promise
  .all([first, second])
  .then(results => {
    // results = ['Batman', 'Joker']
  });
```

What happens if one of the promises get rejected? The returned promise gets rejected, and we won't know what happened with the others.

```javascript
const first = Promise.resolve('Batman');
const second = Promise.reject(new Error('Joker'));

Promise
  .all([first, second])
  .then(results => {
    // we won't get here
  })
  .catch(error => {
    // Error: Joker
  });
```

We can't wait for all the promises to finish even if some of them would be fulfilled.

### Promise.race ([docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race))

The promise returned from the `race` function fulfills or rejects as soon as one of the passed promises resolve or reject. It is useful if you are interested in the first result and want to neglect the slow ones.

```javascript
const first = Promise.resolve('Batman');
const second = Promise.resolve('Joker');

Promise
  .race([first, second])
  .then(result => {
    // result = 'Batman' or 'Joker'
  });
```

The same happens when one of the promises get rejected.

```javascript
const first = Promise.resolve('Batman');
const second = Promise.reject(new Error('Joker'));

Promise
  .race([first, second])
  .then(result => {
    // we get here
  })
  .catch(error => {
    // or here
  });
```

We can't wait for the first promise to resolve if the previous one is rejected.

### The future

The upcoming versions give us two new combinators that will help us overcome the limitations of `all` and `race`. The new versions will also introduce new methods to handle failed operations easier.

### Promise.allSettled ([docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled))

The `all` combinator takes multiple promises and returns a single promise that resolves when all the inputs are completed or rejected. The big difference to the `all` combinator is that it won't be rejected if one the promises reject. `allSettled` will wait for all the others and return both fulfilled and rejected promise results.

```javascript
const first = Promise.resolve('Batman');
const second = Promise.reject(new Error('Joker'));
  
Promise
  .allSettled([first, second])
  .then(results => {
    // results = [
      { status: 'fulfilled', value: 'Batman' }, 
      { status: 'rejected', reason: Error: Joker }
    ]
  });
```

For every item that is fulfilled, we get an object with the `status` property `fulfilled` and the `value` property containing the return value of that promise. For rejected items, we get an object with the `status` property `rejected` and the `reason` property containing the error.

If you want to separate rejected and fulfilled promises, you will have to run a quick filter on the result array.

### Promise.any ([docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/any))

The promise returned from the `any ` function waits until one of the supplied promises resolve. It will still resolve when some of the promises fail. If all the promises reject, the `race` function will also reject.

```javascript
const first = Promise.resolve('Batman');
const second = Promise.reject(new Error('Joker'));
  
Promise
  .any([first, second])
  .then(result => {
    // result = 'Batman'
  });
```

It is a great way to wait for the first successful operation to complete and ignore the rest.

### Promise.prototype.finally ([docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally))

Promises have two states: fulfilled or rejected. When the promise is fulfilled it executes the `then` callback, when rejected the `catch` callback. What happens if we want to run some cleanup commands afterward? We have to include it in both callbacks. Here is where the `finally` method becomes the gamechanger because it is called in both scenarios.

```javascript
const second = Promise.reject(new Error('Joker'));

second
  .then(result => {})
  .catch(error => {})
  .finally(() => {
    // do some cleanup
  });
```

### Promise.try

The method `try` receives a function that can throw synchronous errors and return rejected promises, and it will convert both types to a rejected promise.

```javascript
Promise.try(() => {
  throw new Error('Joker'); // synchronous
  return Promise.reject(new Error('Joker')) // asynchronous
});
```

It can come in handy when you do synchronous operations before asynchronous ones, for example in a command-line script. If you have synchronous code, error handling will be in a try-catch block.  Asynchronous codes error handling will be in a catch callback. With `Promise.try`, you won't need separate error handling.

If the method is still not precise I would recommend reading [this detailed article](http://cryto.net/~joepie91/blog/2016/05/11/what-is-promise-try-and-why-does-it-matter/) about the subject.

### Availability

`Promise.prototype.finally` and `Promise.allSettled` are available in all modern browsers and in Node.js (from version 12), but the others are still in the draft stage. We need the corresponding shims to use them.

```javascript
require('promise.allSettled').shim();
require('promise.any').shim();
require('promise.finally').shim();
require('promise.try').shim();
```

You can find them under [ECMAScript shims](https://github.com/es-shims?utf8=%E2%9C%93&q=promise&type=&language=).

### Summary

Organizing asynchronous code got a massive leap with Promises. It became more comfortable and more readable. Nowadays, the TC39 committee is working on how to make it more natural. The result is the two new combinator functions (`allSettled`, `any`), and the `finally` method along with the `try` method. If you like these methods, start using them today with one of the shims.