napo napo - 6 months ago 25
Javascript Question

promise.all inside a forEach loop — everything firing at once

In a Node app, I need to iterate through some items in a synchronous fashion, but some of the operations inside the loop are asynchronous. My code right now looks like so:

someAPIpromise().then((items) => {
items.forEach((item) => {
Promise.all[myPromiseA(item), myPromiseB(item)]).then(() => {
doSomethingSynchronouslyThatTakesAWhile();
});
}
}


This works wonders when the
items
is an array of 1. But, once there's more than one item,
promise.all()
will just fire off instantly for every item in the array, without waiting for the operation in the loop to end.

All that to say... how can I ensure that the entire operation for each item in the array is run synchronously (even if some operations are async and return a promise)?

Thanks so much!

N

Answer

All righty... the way we were able to get it to work: array.reduce() with the help of Promises. The end result:

myAsyncAPIcall.then(items => {
    items.reduce((current, nextItem) => {
        return current.then(() => {
          return new Promise(res => {
             Promise.all([myPromiseA(nextItem), myPromiseB(nextItem]).then(() => {
               someSynchronousCallThatTakesAWhile(nextItem);
               res();
             }).catch(err => {
                   console.log(err);
             });
          });
        });
    }, Promise.resolve())
})

The way it works is, by wrapping each item of the array in its own Promise(resolve, reject), we can ensure that each iteration is run synchronously, as the completion of one iteration will trigger the need to resolve the next Promise, and so on and so forth. Within each promise resolving, calls can get kicked off asynchronously as much as you want, with the knowledge that they will only be scoped to the parent promise until it finishes.

I hope this helps folks!