4

I am wanting to do something like the following in a React component:

const someArray = [/*stuff*/]
const results = []
someArray.forEach(async item => {

  const result = await someAsyncFunction(item)
  results.push(result)
})

How can I know when all the results have returned then do something?

If I was using $q, in AngularJS, I could do

var results = []
someArray.forEach(function(item) {
  var result = someAsyncFunctionThatReturnsAPromise(item);
  results.push(result);
});

$q.all(results).then(function() {
  // do something
});
dfritch
  • 329
  • 1
  • 3
  • 13
  • 3
    use `Promise.all(/* Your Promise Array */).then(...)`? – CRice Oct 20 '17 at 20:42
  • You're making your code synchronous, so isn't the order of operations guaranteed? Meaning that if you put `console.log(results)` after your forEach loop, it would have all the values. That's the beauty of async/await. – Chase DeAnda Oct 20 '17 at 20:45
  • 1
    @ChaseDeAnda Unfortunately you can't use forEach with async / await, but a basic for loop will work.. – Keith Oct 20 '17 at 20:47
  • @Keith Ah, okay thanks I didn't know that. OP check out this post https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop – Chase DeAnda Oct 20 '17 at 20:48
  • As @CRice said but you will have to remove the `async` `await` – Kevin Farrugia Oct 20 '17 at 20:51
  • You have a couple of options,. replace forEach with a normal for loop. Use `Promise.all`, but do be aware Promise.all can cause performance issues on big arrays, due to thrashing. I personally think a Promise compatible map like Bluebirds http://bluebirdjs.com/docs/api/promise.map.html is the most flexible, due to the concurrency option. – Keith Oct 20 '17 at 20:52
  • If I'm not mistaken, you *can* `await Promise.all()`. –  Oct 20 '17 at 20:55
  • @hayavuk `If I'm not mistaken`,.. Indeed your not mistaken, you can use `await` on anything that returns a promise, and Promise.all returns a Promise.. – Keith Oct 20 '17 at 20:58

2 Answers2

6

You'd do exactly the same thing as if it wasn't a React component:

Promise.all(someArray.map(someAsyncFunction)).then(results => {
  // do stuff with results
});

Of course you can also use q, which $q is based on. It's up to you.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
1

In addition to the answer from Felix, inside an async function, you can also await on the results from Promise.all(), so:

const results = await Promise.all(someArray.map(someAsyncFunction));