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

前端 未结 5 1959
暗喜
暗喜 2020-12-03 12:38

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:

5条回答
  •  隐瞒了意图╮
    2020-12-03 13:23

    You're constructing several promises, but they are all asynchronous. You construct Promise1, Promise2, Promise3, ... but once they're in the wild they are all firing simultaneously. If you want synchronous behavior you've got to chain them together so Promise1's .then() executes Promise2 and so on. In the past I've used Array.reduce for this.

    someAPIpromise().then((items) => {
        items.reduce((accumulator, current) =>
            accumulator.then(() =>
                 Promise.all[myPromiseA(item), myPromiseB(item)]).then(() => 
                     doSomethingSynchronouslyThatTakesAWhile();
                 )
            )
        , Promise.resolve());
    

    You can write this as a helper function if you like, which may make things clearer.

    function execSequentially (arr, func) {
        return arr.reduce(
            (accumulator, current) => accumulator.then(() => func(current)), 
            Promise.resolve());
    }
    

    That function is executed as

    execSequentially(items, item => console.log(item));
    

    of course replacing console.log with what you want to do.

    The helper function approach is also less invasive of a change. The helper applied to your original code:

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

提交回复
热议问题