DEV Community

Yash Soni
Yash Soni

Posted on

JavaScript Promise Combinators - in 3 mins!

In Software Development, Parallelism is the key to better performance.

It means to carry out long-running asynchronous operations in parallel rather than serially (whenever possible).

Preface:

Imagine you have to fetch quotes using a REST API, and there are 7 different categories of quotes you want to have (eg. life, love, inspirational, etc). Assume each API call takes 1 sec to give back a response.

Now let's say, you want to have all 7 quotes before you show it on UI. How would you address this?

If you call it serially, it will take 7 seconds total (1 for each category).

But these tasks are not related, meaning the order of their execution is not important, hence they can be carried out in parallel.

JavaScript has a fun way to deal with such scenarios using Promise Combinators.


What are Promise Combinators?

Promise Combinators, as I understand, are utility methods to deal with multiple promises that need to be executed in parallel.

Each combinator method takes in an array of promises as an argument.

Each combinator method in-turn returns a Promise.

Let's explore them one-by-one. 🤓


Promise.all()

  • This is the most used kind of combinator. An example scenario will be the one discussed above - get multiple Quotes in parallel.
  • IMPORTANT: all() will settle if all the supplied promises have fulfilled, or if any of them is rejected.
  • Always surround call to Promise.all() by try { ... } catch(e) { ... } blocks.
  • When we await Promise.all(), the result will be an array of objects returned for each promise supplied.

Promise.race()

  • This is mostly used in conditions where we want to race the execution of promises against time. An example would be, "Get me all the quotes within 500ms or you fail".
  • This is not at all limited to just race against time, it can also be a race between many asynchronous operations.
  • IMPORTANT: race() will settle if any of the supplied promises have fulfilled or rejected. Meaning, the race will terminate after first success or failure.
  • Always a good practice to surround Promise.race() call by try { ... } catch(e) { ... } blocks.
  • When we await Promise.race(), the result will be the return value of the first settled promise.

Tip: Play around with the timeout value in raceToGetData(500); to see a different result. Try 10 😀

Promise.allSettled()

  • Introduced in ES2020, allSettled combinator should be used when the result of each promise supplied doesn't matter (either fulfilled or rejected), but still want to execute each one of it.
  • IMPORTANT: allSettled() will settle when all the supplied promises are settled.
  • When we await Promise.allSettled(), the result will be an array of result values of all the settled promises.

Promise.any()

  • Introduced in ES2021, any combinator should be used when you want the result of the first fulfilled promise.
  • The only difference from race combinator is that the promise rejections are neglected here.
  • IMPORTANT: any() will settle when any of the supplied promise is fulfilled.
  • When we await Promise.any(), the result will be the result of the first fulfilled promise. If all promises are rejected, then an error will be thrown.
  • Hence, it becomes important to surround Promise.any() call by try { ... } catch(e) { ... } blocks.


P.S.: Check the browser support for any() and allSettled() combinators as they are relatively new. all() and race() are widely supported across all major browser platforms.

Let me know what you guys think! 💬

Follow me on Twitter for some awesome JavaScript tips and quizzes. Likes & Shares are highly appreciated! ❤️

Top comments (0)