Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use promise.all()?

This is more of a conceptual question. I understand the Promise design pattern, but couldn't find a reliable source to answer my question about promise.all():

What is(are) the correct scenario(s) to use promise.all()

OR

Are there any best practices to use promise.all()? Should it be ideally used only if all of the promise objects are of the same or similar types?

The only one I could think of is:

  • Use promise.all() if you want to resolve the promise only if all of the promise objects resolve and reject if even one rejects.
like image 499
nikjohn Avatar asked Jul 04 '16 08:07

nikjohn


People also ask

What is the difference between Promise and Promise all?

With promise methods like Promise. all() — which takes an array of promises as an argument a returns a promise that resolves when all the passed promises have been resolved — and the concept of chaining promises, you can write cleaner and easier to read code.

Does Promise all throw error?

Promise. all is all or nothing. It resolves once all promises in the array resolve, or reject as soon as one of them rejects. In other words, it either resolves with an array of all resolved values, or rejects with a single error.

What is the use of Promise Any ()?

Promise. any() takes an iterable of Promise objects. It returns a single promise that fulfills as soon as any of the promises in the iterable fulfills, with the value of the fulfilled promise.

What is the fulfilled value of Promise all ()?

all() Method: Fulfillment: The returned promise is fulfilled, If the passed iterable is empty, then this method returns an promise synchronously which is already resolved. If all of the passed promises are fulfill, the returned Promises are fulfilled asynchronously.


3 Answers

I'm not sure anyone has really given the most general purpose explanation for when to use Promise.all() (and when not to use it):

What is(are) the correct scenario(s) to use promise.all()

Promise.all() is useful anytime you have more than one promise and your code wants to know when all the operations that those promises represent have finished successfully. It does not matter what the individual async operations are. If they are async, are represented by promises and your code wants to know when they have all completed successfully, then Promise.all() is built to do exactly that.

For example, suppose you need to gather information from three separate remote API calls and when you have the results from all three API calls, you then need to run some further code using all three results. That situation would be perfect for Promise.all(). You could so something like this:

Promise.all([apiRequest(...), apiRequest(...), apiRequest(...)]).then(function(results) {
    // API results in the results array here
    // processing can continue using the results of all three API requests
}, function(err) {
    // an error occurred, process the error here
});

Promise.all() is probably most commonly used with similar types of requests (as in the above example), but there is no reason that it needs to be. If you had a different case where you needed to make a remote API request, read a local file and read a local temperature probe and then when you had data from all three async operations, you wanted to then do some processing with the data from all three, you would again use Promise.all():

Promise.all([apiRequest(...), fs.promises.readFile(...), readTemperature(...)]).then(function(results) {
    // all results in the results array here
    // processing can continue using the results of all three async operations
}, function(err) {
    // an error occurred, process the error here
});

On the flip side, if you don't need to coordinate among them and can just handle each async operation individually, then you don't need Promise.all(). You can just fire each of your separate async operations with their own .then() handlers and no coordination between them is needed.

In addition Promise.all() has what is called a "fast fail" implementation. It returns a master promise that will reject as soon as the first promise you passed it rejects or it will resolve when all the promises have resolved. So, to use Promise.all() that type of implementation needs to work for your situation. There are other situations where you want to run multiple async operations and you need all the results, even if some of them failed. Promise.all() will not do that for you directly. Instead, you would likely use something like Promise.settle() for that situation. You can see an implementation of .settle() here which gives you access to all the results, even if some failed. This is particularly useful when you expect that some operations might fail and you have a useful task to pursue with the results from whatever operations succeeded or you want to examine the failure reasons for all the operations that failed to make decisions based on that.

Are there any best practices to use promise.all()? Should it be ideally used only if all of the promise objects are of the same or similar types?

As explained above, it does not matter what the individual async operations are or if they are the same type. It only matters whether your code needs to coordinate them and know when they all succeed.


It's also useful to list some situations when you would not use Promise.all():

  1. When you only have one async operation. With only one operation, you can just use a .then() handler on the one promise and there is no reason for Promise.all().
  2. When you don't need to coordinate among multiple async operations.
  3. When a fast fail implementation is not appropriate. If you need all results, even if some fail, then Promise.all() will not do that by itself. You will probably want something like Promise.allSettled() instead.
  4. If your async operations do not all return promises, Promise.all() cannot track an async operation that is not managed through a promise.
like image 141
jfriend00 Avatar answered Oct 10 '22 07:10

jfriend00


Promise.all is for waiting for several Promises to resolve in parallel (at the same time). It returns a Promise that resolves when all of the input Promises have resolved:

// p1, p2, p3 are Promises
Promise.all([p1, p2, p3])
  .then(([p1Result, p2Result, p3Result]) => {
    // This function is called when p1, p2 and p3 have all resolved.
    // The arguments are the resolved values.
  })

If any of the input Promises is rejected, the Promise returned by Promise.all is also rejected.

A common scenario is waiting for several API requests to finish so you can combine their results:

 const contentPromise = requestUser();
 const commentsPromise = requestComments();

 const combinedContent = Promise.all([contentPromise, commentsPromise])
   .then(([content, comments]) => {
     // content and comments have both finished loading.
   })

You can use Promise.all with Promise instance.

like image 45
joews Avatar answered Oct 10 '22 06:10

joews


It's hard to answer these questions as they are the type that tend to answer themselves as one uses the available APIs of a language feature. Basically, it's fine to use Promises any way that suits your use case, so long as you avoid their anti-patterns.

What is(are) the correct scenario(s) to use promise.all()

Any situation in which an operation depends on the successful resolution of multiple promises.

Are there any best practices to use promise.all()? Should it be ideally used only if all of the promise objects are of the same or similar types?

Generally, no and no.

like image 22
sdgluck Avatar answered Oct 10 '22 05:10

sdgluck