Search code examples
javascriptpromisees6-promise

Wait for promises inside Promise.all to finish before resolving it


I have a Promise.all that executes asynchronous functions mapped on an array input if it's not null and then resolve data to a previously defined Promise:

Promise.all((inputs || []).map(input => {
  return new Promise((resolve, reject) => {
    someAsyncFunc(input)
    .then(intermediateOutput => {
      someOtherAsyncFunc(intermediateOutput )
      .then(output => {
        return Promise.resolve(output )
      })
      .catch(reason=> {
        return Promise.reject(reason)
      })
    })
    .catch(reason => {
      return Promise.reject(reason);
    })
  })
  .then(outputs => {
    resolve(outputs)
  })
  .catch(reason => {
    reject(reason)
  })
}))

I only get empty outputs before even someAsyncFunc finishes its work. How can make Promise.all wait for the promises inside to finish their asynchronous work ?


Solution

  • See jfriend's comment.

    someAsyncFunc and someOtherAsyncFunc are function that properly return a promise with something like return new Promise(/*...*/);

    this is useless:

    .then(output => {
      return Promise.resolve(output )
    })
    

    read the Promise documentation

    same

    .catch(reason=> {
      return Promise.reject(reason)
    })
    

    the Promise is already rejecting, you don't need to catch and reject yourself

    to make sure Promises are chainable you need to return the Promise

    // ...
    return new Promise((resolve, reject) => {
      if(inputs == null)
        resolve([]);
      else {
        Promise.all(inputs.map(input => {
          return someAsyncFunc(input)
            .then(someOtherAsyncFunc)
        }))
          .then(resolve)
          .catch(reject)
      }
    });
    

    note I would rather not make the arry for Promise.all inline, it adds visual clutter:

    return new Promise((resolve, reject) => {
      if(inputs == null)
        resolve([]);
      else {
        const myPromises = inputs.map(input => {
          return someAsyncFunc(input)
            .then(someOtherAsyncFunc)
        });
        Promise.all(myPromises)
          .then(resolve)
          .catch(reject)
      }
    });
    

    it may still fail if you made other mistakes.