1

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.

frost kazuma
  • 350
  • 1
  • 8
  • 24
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all – Harsha Venkataramu Sep 01 '20 at 08:29
  • 2
    No. `Promise.all` simply checks the array of promises and waits for *all of them to be resolved*. When you are doing `Array.prototype.map` you're already executing/running the promises on the fly *and* pushing them into the array at the same time. – Terry Sep 01 '20 at 08:30
  • as i know it's not running in parrallel , it's just return 1 resolve promise when all promise in array you input resolved – Khanh Le Tran Sep 01 '20 at 08:32
  • 1
    @KhanhLeTran - Incorrect. The asynchronous operations do indeed run in parallel (modulo resource contention). – T.J. Crowder Sep 01 '20 at 08:33

1 Answers1

6

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(...).

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875