如何返回许多 Promise 并在做其他事情之前等待它们全部

新手上路,请多包涵

我有一个循环,它调用一个异步执行操作的方法。这个循环可以多次调用该方法。在此循环之后,我还有另一个循环,仅当所有异步操作完成后才需要执行该循环。

所以这说明了我想要的:

 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 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 684
2 个回答

您可以为此使用 Promise.all规范MDN ):它接受一堆单独的承诺,并返回一个单一的承诺,当您给它的所有承诺都得到解决时,该承诺就会得到解决,或者当任何承诺被拒绝时他们中的一个被拒绝了。

所以如果你做出 doSomeAsyncStuff 返回一个承诺,那么:

     const promises = [];
//  ^^^^^−−−−−−−−−−−−−−−−−−−−−−−−−−− use `const` or `let`, not `var`

    for (let i = 0; i < 5; i++) {
//       ^^^−−−−−−−−−−−−−−−−−−−−−−−− added missing declaration
        promises.push(doSomeAsyncStuff());
    }

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

MDN 在 这里 有一篇关于承诺的文章。我还在我的书 JavaScript:新玩具 的第 8 章中详细介绍了 promsies,如果您有兴趣,可以在我的个人资料中找到链接。

这是一个例子:

  function doSomethingAsync(value) {
     return new Promise((resolve) => {
         setTimeout(() => {
             console.log("Resolving " + value);
             resolve(value);
         }, Math.floor(Math.random() * 1000));
     });
   }

   function test() {
       const promises = [];

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

       Promise.all(promises)
           .then((results) => {
               console.log("All done", results);
           })
           .catch((e) => {
               // Handle errors here
           });
   }

   test();

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

解析 3
解析 2
解析 1
解析 4
正在解析 0
全部完成 [0,1,2,3,4]

原文由 T.J. Crowder 发布,翻译遵循 CC BY-SA 4.0 许可协议

一个可重用的函数非常适合这种模式:

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

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

  return Promise.all(promises);
}

操作示例:

 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 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题