我有一个函数 foo ,它在循环中进行多个(并行)异步调用。我需要等到所有呼叫的结果都可用。如何从 foo 返回完整结果,或者在所有数据可用后触发某些处理?
I have a function foo which makes multiple (parallel) asynchronous calls in a loop. I need to somehow wait until the results of all of the calls are available. How can I return the full results from foo, or otherwise trigger some processing after all of the data is available?
我尝试将每个结果添加到数组中,但是直到我需要使用它之后才会填充数组。
I tried adding each result to an array, but then the array isn't populated until after the point where I need to use it.
function foo() { var results = []; for (var i = 0; i < 10; i++) { someAsyncFunction({someParam:i}, function callback(data) { results.push(data); }); } return results; } var result = foo(); // It always ends up being an empty array at this point.注意:这个问题是按照现有通用如何从异步调用中返回响应?问题。这个问题有一些很好的答案,但不包括多个异步调用。还有一些其他问题提到多个调用,但我找不到任何基于循环的调用,有些只有jQuery答案等等。我希望这里有一些不依赖于特定库的通用技术。
Note: this question is deliberately generic along the lines of the existing generic "How do I return the response from an asynchronous call?" question. That question has some excellent answers, but doesn't cover multiple async calls. There are some other questions that mention multiple calls, but I couldn't find any loop-based ones, and some only had jQuery answers, etc. I'm hoping here for some generic techniques that don't depend on a particular library.
推荐答案使用promises。准确地说, Promise.all 就是为此设计的。
Use promises. Precisely, Promise.all was designed for this.
它接受一个数组(或可迭代)的promises,并返回一个新的promise,当阵列的所有承诺都已解决。否则,它拒绝任何数组的承诺拒绝。
It takes an array (or iterable) of promises, and returns a new promise which is resolved when all the promises of the array have been resolved. Otherwise, it rejects when any promise of the array rejects.
function someAsyncFunction(data, resolve, reject) { setTimeout(function() { if(Math.random() < .05) { // Suppose something failed reject('Error while processing ' + data.someParam); } else { // Suppose the current async work completed succesfully resolve(data.someParam); } }, Math.random() * 1000); } function foo() { // Create an array of promises var promises = []; for (var i = 0; i < 10; i++) { // Fill the array with promises which initiate some async work promises.push(new Promise(function(resolve, reject) { someAsyncFunction({someParam:i}, resolve, reject); })); } // Return a Promise.all promise of the array return Promise.all(promises); } var result = foo().then(function(results) { console.log('All async calls completed successfully:'); console.log(' --> ', JSON.stringify(results)); }, function(reason) { console.log('Some async call failed:'); console.log(' --> ', reason); });
请注意,结果将根据到承诺数组的顺序,而不是承诺被解决的顺序。
Note that the results will be given according to the order of the array of promises, not in the order that the promises were resolved in.
更多推荐
如何在循环中返回多个(并行)异步函数调用的累积结果?
发布评论