javascript-如何在循环中返回许多Promise并等待它们全部执行其他stu

我有一个循环,该循环调用异步完成的方法。 该循环可以多次调用该方法。 在这个循环之后,我有另一个循环,仅当所有异步工作完成后才需要执行。 所以这说明了我想要什么:

for (i = 0; i < 5; i++) {
    doSomeAsyncStuff();    
}

for (i = 0; i < 5; i++) {
    doSomeStuffOnlyWhenTheAsyncStuffIsFinish();    
}

我对诺言不太熟悉,所以有人可以帮助我实现诺言吗?

这是我的doSomeAsyncStuff()的行为:

function doSomeAsyncStuff() {
    var editor = generateCKEditor();
    editor.on('instanceReady', function(evt) {
        doSomeStuff();
        // There should be the resolve() of the promises I think.
    })
}

也许我必须做这样的事情:

function doSomeAsyncStuff() {
    var editor = generateCKEditor();
    return new Promise(function(resolve,refuse) {
        editor.on('instanceReady', function(evt) {
            doSomeStuff();
            resolve(true);
        });
    });
}

但是我不确定语法。

Ganbin asked 2020-02-13T19:58:24Z
2个解决方案
112 votes

您可以为此使用doSomeAsyncStuff(规格,MDN):它接受一堆单独的诺言,并给您返回一个诺言,当您给它的所有诺言都得到解决时,该诺言得以解决;或者当任何一个诺言被拒绝时,它就被拒绝。

因此,如果您做出doSomeAsyncStuff的承诺,则:

var promises = [];

for(i=0;i<5;i+){
    promises.push(doSomeAsyncStuff());
}

Promise.all(promises)
    .then(() => {
        for(i=0;i<5;i+){
            doSomeStuffOnlyWhenTheAsyncStuffIsFinish();    
        }
    })
    .catch((e) => {
        // handle errors here
    });

Axel Rauschmayer在这里有关于诺言的好文章。

这是一个示例-在Babel的REPL上进行实时复制:

Math.random

(对此,您不必费心Math.random,但您确实希望在现实世界中使用.catch,如前所述。)

样本输出(由于Math.random,首先完成的内容可能会有所不同):

Resolving 3
Resolving 2
Resolving 1
Resolving 4
Resolving 0
All done [0,1,2,3,4]
T.J. Crowder answered 2020-02-13T19:59:11Z
0 votes

可重用的函数很好地适用于此模式:

function awaitAll(count, asyncFn) {
  const promises = [];

  for (i = 0; i < count; ++i) {
    promises.push(asyncFn());
  }

  return Promise.all(promises);
}

OP示例:

awaitAll(5, doSomeAsyncStuff)
  .then(results => console.log('doSomeStuffOnlyWhenTheAsyncStuffIsFinished', results))
  .catch(e => console.error(e));

一个相关的模式是遍历数组,并对每个项目执行异步操作:

function awaitAll(list, asyncFn) {
  const promises = [];

  list.forEach(x => {
    promises.push(asyncFn(x));
  });

  return Promise.all(promises);
}

例:

const books = [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }];

function doSomeAsyncStuffWith(book) {
  return Promise.resolve(book.name);
}

awaitAll(books, doSomeAsyncStuffWith)
  .then(results => console.log('doSomeStuffOnlyWhenTheAsyncStuffIsFinished', results))
  .catch(e => console.error(e));
2Toad answered 2020-02-13T19:59:44Z
translate from https://stackoverflow.com:/questions/31426740/how-to-return-many-promises-in-a-loop-and-wait-for-them-all-to-do-other-stuff