Lev
Lev

Reputation: 15734

How can I check that multiple async operations have completed?

I have a case where I want to do something once 10 async calls have completed

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?

How can I achieve this?

Upvotes: 2

Views: 397

Answers (4)

amaksr
amaksr

Reputation: 7745

You can just count responses in separate variable, and check it before continue:

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

Upvotes: 0

martin
martin

Reputation: 96959

This depends on whether you know the async operations (read Observables/Promises) beforehand or not.

For example if you can compose an array of Observables then the easiest way is to use forkJoin:

let observables = [ ... ];
Observable.forkJoin(observables)
    .subscribe(results => /* whatever */);

Otherwise, you can just mergeMap them into a single chain a listen only to the complete signal:

Observable.range(1, 10) // or whatever
    .mergeMap(i => /* return Observable here */)
    .subscribe(undefined, undefined, () => console.log('all done'));

Upvotes: 3

ZahiC
ZahiC

Reputation: 14707

'The Rx way' is to use 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));

Upvotes: 1

trincot
trincot

Reputation: 350821

You have to make your loop asynchronous, so that an iteration will only occur when the next response is available. Here is how you can do that:

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

The loop function is immediately invoked with an empty array as argument. When you get the response, you call that function again, now with the extended array, ...etc. Once you have 10 responses, you call another function that will do something with the final array.

As you can see, I chose to eliminate the variable i, since arr.length has the same value.

Note that this kind of asynchronous processing can also be done with promises and some recent features like async and await. You might want to look into that. Here is an example

Upvotes: 0

Related Questions