【问题标题】:How can I check that multiple async operations have completed?如何检查多个异步操作是否已完成?
【发布时间】:2017-05-30 12:37:22
【问题描述】:
我有一个案例,我想在 10 个异步调用完成后做某事
let i = 0;
let array = [];
do {
this.service.getSomething(i).subscribe(response => {
array[i] = response;
});
} while (i < 10);
// how can I know when the 10 async calls have completed?
我怎样才能做到这一点?
【问题讨论】:
标签:
javascript
promise
rxjs
【解决方案1】:
这取决于你是否事先知道异步操作(读取 Observables/Promises)。
例如,如果您可以组成一个 Observables 数组,那么最简单的方法是使用forkJoin:
let observables = [ ... ];
Observable.forkJoin(observables)
.subscribe(results => /* whatever */);
否则,您可以只将mergeMap 他们放到一个链中只听complete 信号:
Observable.range(1, 10) // or whatever
.mergeMap(i => /* return Observable here */)
.subscribe(undefined, undefined, () => console.log('all done'));
【解决方案2】:
'Rx 方式'是使用forkJoin:
const requestParams = [0,1,2,3,4,5,6,7,8,9];
const requests = requestParams.map(i => this.service.getSomething(i));
Observable.forkJoin(requests).subscribe(reponseArray => alldone(responseArray));
【解决方案3】:
您必须使循环异步,以便仅在下一个响应可用时才会发生迭代。您可以这样做:
(function loop(arr) {
if (arr.length >= 10) return alldone(array); // all done
this.service.getSomething(arr.length).subsribe(response => {
loop(array.concat(response)); // "recursive" call
});
})([]); // <--- pass empty array as argument to the loop function
function alldone(arr) {
console.log(arr);
}
loop 函数会立即以一个空数组作为参数调用。当你得到响应时,你再次调用该函数,现在使用扩展数组,......等等。一旦你有 10 个响应,你就调用另一个函数来处理最终的数组。
如您所见,我选择消除变量i,因为arr.length 具有相同的值。
请注意,这种异步处理也可以通过 Promise 和一些最近的功能(如 async 和 await)来完成。你可能想调查一下。 Here is an example
【解决方案4】:
您可以只计算单独变量中的响应,并在继续之前检查它:
let i = 0;
let array = [];
var finishedCnt=0;
do {
this.service.getSomething(i).subsribe(response => {
array[i] = response;
finishedCnt++;
if(finishedCnt>=10) {
// all requests done, do something here
}
});
} while (i < 10);