Javascript 如何在循环中返回许多 Promise 并等待它们全部执行其他操作
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31426740/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to return many Promises in a loop and wait for them all to do other stuff
提问by Ganbin
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:
这是我的doSomeAsyncStuff()
行为方式:
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.
但我不确定语法。
回答by T.J. Crowder
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.
你可以使用Promise.all
( spec, MDN):它接受一堆单独的承诺,并给你一个单一的承诺,当你给它的所有承诺都得到解决时,这个承诺得到解决,或者当其中任何一个被拒绝时被拒绝。
So if you make doSomeAsyncStuff
return a promise, then:
所以如果你让doSomeAsyncStuff
return 成为一个承诺,那么:
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 has a good article on promises here.
阿克塞尔Rauschmayer先生对诺言的好文章在这里。
Here's an example - live copy on Babel's REPL:
这是一个例子 - Babel 的 REPL 上的实时副本:
function doSomethingAsync(value) {
return new Promise((resolve) => {
setTimeout(() => {
console.log("Resolving " + value);
resolve(value);
}, Math.floor(Math.random() * 1000));
});
}
function test() {
let i;
let promises = [];
for (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();
(对此并不介意
.catch
.catch
,但您确实想要.catch
.catch
现实世界中的那些,如前所示。)Sample output (because of the Math.random
, what finishes first may vary):
示例输出(由于 ,Math.random
首先完成的内容可能会有所不同):
Resolving 3 Resolving 2 Resolving 1 Resolving 4 Resolving 0 All done [0,1,2,3,4]
回答by 2Toad
A reusable function works nicely for this pattern:
可重用函数非常适合这种模式:
function awaitAll(count, asyncFn) {
const promises = [];
for (i = 0; i < count; ++i) {
promises.push(asyncFn());
}
return Promise.all(promises);
}
OP example:
操作示例:
awaitAll(5, doSomeAsyncStuff)
.then(results => console.log('doSomeStuffOnlyWhenTheAsyncStuffIsFinished', results))
.catch(e => console.error(e));
A related pattern, is iterating over an array and performing an async operation on each item:
一个相关的模式是迭代数组并对每个项目执行异步操作:
function awaitAll(list, asyncFn) {
const promises = [];
list.forEach(x => {
promises.push(asyncFn(x));
});
return Promise.all(promises);
}
Example:
例子:
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));
回答by JoeTidee
const doSomeAsyncStuff = async (funcs) => {
const allPromises = funcs.map(func => func());
return await Promise.all(allPromises);
}
doSomeAsyncStuff([
() => new Promise(resolve => setTimeout(() => resolve(), 100)),
() => new Promise(resolve => setTimeout(() => resolve(), 100)),
() => new Promise(resolve => setTimeout(() => resolve(), 100)),
() => new Promise(resolve => setTimeout(() => resolve(), 100)),
() => new Promise(resolve => setTimeout(() => resolve(), 100)),
]);