Search code examples
rxjssubscription

How can I wait for multiple subscriptions?


I'm trying to make an API call for each element of an array, and emit an specific event if every API response is true.

I was doing the following:

let emit = true

array.forEach(element => {
  this.service.getElement(element).subscribe(loaded => {
      if(!loaded){
         emit = false;
      }
  });
});

this.loaded.emit(emit);

But the last line always emits true

How can I wait for every request to be resolved before making the output event emission?


Solution

  • So the last line will always emit true because the service code is executed asynchronously. This means that it executes everything except the callback function in the subscribe method. This callback function executed once the stream emits a new element. I guess, you are making Http requests to an endpoint here. If so, the callback function is executed for each Http response and the order is not guaranteed.

    What you can do is:

    forkJoin(
      ...array.map(e => this.service.getElement(e))
    ).subscribe(responseArray =>
      console.log(responseArray);
      console.log('Complete');
    );
    

    The callback only executes if all Http response are available. And responseArray has the exact same order as the elements in the array.

    Note: Keep in mind that if you do

    let emit = false;
    forkJoin(...).subscribe(() => emit = true);
    console.log(emit);
    

    It would print you false, because the callback executes async. If that seems like strange behaviour for you, I'd highly recommend to read about the JavaScript Eventloop.