且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-12-05 22:10:52

你可以使用 Promise.all (规范, MDN):它接受一堆单独的 Promise,并返回一个单一的 Promise,当你给它的所有 Promise 都被解决时,该 Promise 被解决,或者当其中任何一个被拒绝时被拒绝.

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

 const 承诺 = [];//^^^^^−−−−−−−−−−−−−−−−−−−−−−−−−−− 使用 `const` 或 `let`,而不是 `var`for (让 i = 0; i 

MDN 有一篇关于 Promise 的文章这里.我还在我的书 JavaScript: The New Toys 的第 8 章中详细介绍了 Promsies,如果您有兴趣,可以在我的个人资料中链接.

这是一个例子:

 function doSomethingAsync(value) {return new Promise((resolve) => {设置超时(() => {console.log("正在解决" + value);解决(价值);}, Math.floor(Math.random() * 1000));});}功能测试() {常量承诺 = [];for (让 i = 0; i < 5; ++i) {promises.push(doSomethingAsync(i));}Promise.all(承诺).then((结果) => {console.log("全部完成", results);}).catch((e) => {//这里处理错误});}test();

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

解决 3解决 2解决 1解决 4解决 0全部完成 [0,1,2,3,4]

I have a loop which calls a method that does stuff asynchronously. This loop can call the method many times. After this loop, I have another loop that needs to be executed only when all the asynchronous stuff is done.

So this illustrates what I want:

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

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

I'm not very familiar with promises, so could anyone help me to achieve this?

This is how my doSomeAsyncStuff() behaves:

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

Maybe I have to do something like this:

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

But I'm not sure of the syntax.

You can use Promise.all (spec, MDN) for that: It accepts a bunch of individual promises and gives you back a single promise that is resolved when all of the ones you gave it are resolved, or rejected when any of them is rejected.

So if you make doSomeAsyncStuff return a promise, then:

    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 has an article on promises here. I also cover promsies in detail in Chapter 8 of my book JavaScript: The New Toys, links in my profile if you're interested.

Here's an example:

 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();

Sample output (because of the Math.random, what finishes first may vary):

Resolving 3
Resolving 2
Resolving 1
Resolving 4
Resolving 0
All done [0,1,2,3,4]