DEV Community

Cover image for How to Use Promise.all and Promise.race to Speed Up Your JavaScript Code
Emanuele Bartolesi for This is Learning

Posted on

How to Use Promise.all and Promise.race to Speed Up Your JavaScript Code

In my previous article I described how to use Async and Await in Vanilla JavaScript.

In this article, I would like to work with parallel tasks in vanilla JavaScript.
Let's start!

What are promise.all and promise.race?

Promise.all and promise.race are two methods that belong to the Promise object. They allow you to create a single promise that depends on the outcome of multiple promises. The difference between them is how they handle the results of the promises.

  • Promise.all takes an iterable (such as an array) of promises as an argument and returns a promise that resolves with an array of the results of all the promises. If any of the promises rejects, the promise rejects with the reason of the first rejected promise.
  • Promise.race takes an iterable (such as an array) of promises as an argument and returns a promise that resolves or rejects with the result or reason of the first promise that settles. It doesn't matter if the other promises are still pending or not.

How to use promise.all and promise.race?

To use promise.all and promise.race, you don't need to install any library. They are part of the native JavaScript language. You can create promises using the new Promise constructor or using async functions or a mix of both ways:

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('Promise 1'), 1000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => reject('Error Promise 2'), 2000);
});

const promise3 = async () => {
  const response = await fetch('https://example.com/api/data');
  return response.json();
};
Enter fullscreen mode Exit fullscreen mode

To run these promises together, you can use promise.all:

promise.all([promise1, promise2, promise3()])
  .then(results => {
    // results is an array of values from the resolved promises
    console.log(results);
  })
  .catch(error => {
    // error is the reason of the first rejected promise
    console.error(error);
  });
Enter fullscreen mode Exit fullscreen mode

To run these promises in a race, you can use promise.race:

promise.race([promise1, promise2, promise3()])
  .then(result => {
    // result is the value of the first settled promise
    console.log(result);
  })
  .catch(error => {
    // error is the reason of the first settled promise if it rejected
    console.error(error);
  });
Enter fullscreen mode Exit fullscreen mode

Why use promise.all and promise.race?

Using promise.all and promise.race can have several benefits for your code:

  • They can improve the performance of your code by running multiple promises concurrently instead of sequentially.
  • They can simplify your code by avoiding nested promises or async/await syntax.
  • They can make your code more readable and expressive by using descriptive names for your promises.

Conclusion

In this article, I showed you how to use promise.all and promise.race to handle multiple promises in a simple and elegant way. These methods can help you master asynchronous JavaScript and make your code faster and cleaner.

⚠️⚠️⚠️
Even though people commonly refer to the practice of running multiple promises at the same time as "running promises in parallel," it is not actual parallel processing. JavaScript, being a single-threaded language, cannot execute tasks in parallel by itself, except through the use of web workers or worker threads. Parallel processing needs running multiple tasks at the same time, usually on different threads, and JavaScript lacks the ability to do so.

“Note that JavaScript is single-threaded by nature, so at a given instant, only one task will be executing, although control can shift between different promises, making execution of the promises appear concurrent. Parallel execution in JavaScript can only be achieved through worker threads.” - MDN Documentation

⚠️⚠️⚠️

If you have any questions or feedback, feel free to leave a comment below.


Are you interested in learning GitHub but don't know where to start? Try my course on LinkedIn Learning: Learning GitHub.

LinkedIn Learning


Thanks for reading this post, I hope you found it interesting!

Feel free to follow me to get notified when new articles are out 🙂

Top comments (9)

Collapse
 
gnulou profile image
LouDogg

Good read. Thanks

Collapse
 
thumbone profile image
Bernd Wechner

You note that JS is single threaded and quote from the docs "though control can shift between different promises". I think that this is true but saliently, on a voluntary basis, that is any routine that is running will hog the whole of the JS engines attention until it chooses to ceded control. It is worth perhaps researching and reporting on that and how to cede control (from memory, by returning, i.e. completing, or exiting, bailing, or using await, can't recall if there are others offhand)

Collapse
 
miketalbot profile image
Mike Talbot ⭐ • Edited
Collapse
 
kasuken profile image
Emanuele Bartolesi

thanks for sharing.

Collapse
 
miketalbot profile image
Mike Talbot ⭐ • Edited

One of the significant benefits of promises is that they can execute functions external to the JavaScript runtime which may well be able to run in parallel - web requests for instance.

An await in a loop where each one is a web request is a total waste of time if each call can be independently run and the results processed when they are all ready. If calls rely on the results of the previous calls then you don't have any choice - but it's best to engineer this out if at all possible.

Use cases for Promise.race are less common - you could use it to go and call multiple servers to see which one returns first, or try different techniques to solve a problem - but that wouldn't work well if those promises couldn't work in parallel. My most common use case is to use it to provide a timeout.

Using promises it is possible to keep the UI of an application fully responsive during long effort JavaScript but you'll need to code it up or use a library. I explain some of this in the article below.

Collapse
 
wra-sol profile image
Nathaniel Arfin • Edited

Great article! Can you provide me an example use case for Promise.race()?

I just want to note that this (edited) might be misinterpreted

They can improve the performance of your code by running multiple promises concurrently instead of sequentially.

From the Promise docs

Note that JavaScript is single-threaded by nature, so at a given instant, only one task will be executing, although control can shift between different promises, making execution of the promises appear concurrent. Parallel execution in JavaScript can only be achieved through worker threads.

Collapse
 
kasuken profile image
Emanuele Bartolesi

There is a note in the post…

Collapse
 
wra-sol profile image
Nathaniel Arfin

Well it's a good thing you didn't wrap that part in alert symbols, right there in the conclusion, or my comment would be really embarrassing.

Collapse
 
ashcript profile image
As Manjaka Josvah

I think sometimes, it's a good idea to run some promises in parallel, that's why it provides the .all() method. Of course, The event loop handles just one message from the queue and start to handle another one when the previous one is done, but Promise.all() ensures that it returns all the promises results only when all the promises inside the array passed as parameter to the Promise.all() method are resolved. So it can a little bit simulate the case that makes you feel like it's executed in parallel but in reality, it is not.