Node: Using promise.all() to call API’s in parallel?

Tags: , ,



I’m a bit confused how promise.all work, does it run the array of promises in parallel?

So here is a sample code

// index.js

const getSomething = async (args) => {
  return await apiCallHere(args)
}

// Create Array of Promises
const arrayOfPromises = sampleArray.map(sample => new Promise((resolve, reject) => {
      try {
        const something = this.getSomething(sample, args)
        resolve(something) 
      } catch (error) {
        reject(error)
      }
}))

await Promise.all(arrayOfPromises)

From what I observed, Promise.all runs the promises in parallel, and wait for all promises to finish.

Answer

does it run the array of promises in parallel

Promise.all doesn’t, no; your code does (well, probably; see the Notes below). The work is already underway before Promise.all sees the promises. What Promise.all does is give you a promise that will settle when all of the promises you give it are fulfilled (or one of them is rejected).

It’s your code that makes the work run in parallel, by starting the actions that the promises report the completion of (in the map callback) in order to give them to Promise.all in the first place. See *** comments:

// *** `map` is synchronous, it loops all the way through the array
const arrayOfPromises = sampleArray.map(sample => new Promise((resolve, reject) => {
      try {
        const something = this.getSomething(sample, args) // *** This is what starts each thing
        resolve(something) 
      } catch (error) {
        reject(error)
      }
}))

// *** The work is already underway here

// *** This just waits for it to finish
await Promise.all(arrayOfPromises)

Remember that a promise is just a way to observe the completion of an asynchronous process. Promises don’t run anything. They just report the completion of something, along with the fulfillment value or rejection reason.


Notes

If this.getSomething(sample, args) returns a promise, your code is falling prey to the explicit promise creation anti-pattern: There’s no reason to use new Promise here at all. Instead:

const arrayOfPromises = sampleArray.map(sample => this.getSomething(sample, args));

If this.getSomething(sample, args) returns its value immediately, then there’s no point in using promises here at all, because the operations are already complete by the time it returns.

(I assume it doesn’t start an asynchronous process and report completion via a callback instead of a promise, since you haven’t shown a callback but you have shown using the return value.)

The getSomething you’ve shown in the question returns a promise (because it’s an async function), but you wouldn’t call that as this.getSomething(...), just as getSomething(...).



Source: stackoverflow