最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Wait for promises inside Promise.all to finish before resolving it - Stack Overflow

programmeradmin2浏览0评论

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 ?

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 ?

Share Improve this question edited Apr 13, 2017 at 21:54 cartman asked Apr 13, 2017 at 21:05 cartmancartman 1901 gold badge3 silver badges18 bronze badges 3
  • You are very confused about how Promise.all() works. It does not accept a callback like you have it declared in your first line of code. It accepts an array of promises. – jfriend00 Commented Apr 13, 2017 at 21:06
  • return Promise.all(inputs.map(someAsyncFunc)); is probably what you are looking for? – Arthur Cinader Commented Apr 13, 2017 at 21:09
  • @Arthur, yes, but actually I have an other function to call just after someAsyncFunc. i'll edit my code to show that – cartman Commented Apr 13, 2017 at 21:11
Add a ment  | 

2 Answers 2

Reset to default 3

Would not just

return Promise.all((inputs || []).map(input =>
 somePromiseFunc(input).then(someOtherPromiseFunc)
);

work ?

You're not using Promise.all right the first time since it takes an array of promises as input, and not (resolve, reject) => { ... }

Promise.all is going to be rejected as soon as one of the underlying promises fails, so you don't need to try to do something around catch(error => reject(error)

Example:

const somePromiseFunc = (input) => new Promise((resolve, reject) => {
  setTimeout(() => {
    if (input === 0) { reject(new Error('input is 0')); }
    resolve(input + 1);
  }, 1000);
});

const someOtherPromiseFunc = (intermediateOutput) => new Promise((resolve, reject) => {
  setTimeout(() => {
    if (intermediateOutput === 0) { reject(new Error('intermediateOutput is 0')); }
    resolve(intermediateOutput + 1);
  }, 1000);
});

const f = inputs => {
  const t0 = Date.now()
  return Promise.all((inputs || []).map(input => somePromiseFunc(input).then(someOtherPromiseFunc)))
    .then(res => console.log(`result: ${JSON.stringify(res)} (after ${Date.now() - t0}ms)`))
    .catch(e => console.log(`error: ${e} (after ${Date.now() - t0}ms)`));
};

f(null)
// result: [] (after 0ms)

f([1, 0])
// error: Error: input is 0 (after 1001ms)

f([1, -1])
// error: Error: intermediateOutput is 0 (after 2002ms)

f([1, 2])
// result: [3,4] (after 2002ms)

See jfriend's ment.

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.

发布评论

评论列表(0)

  1. 暂无评论