dmd
dmd

Reputation: 387

Why nested subscription is not good?

I know that nested subscriptions should be avoided and rxjs operators should be used, but the articles I found about this issue usually just saying that nested subscriptions is bad without explaining why(besides saying 'may cause issues') .

I'm wondering if anyone can help on this one? Thank you.

Upvotes: 13

Views: 6686

Answers (2)

Chund
Chund

Reputation: 449

Good that you are asking since this is a common problem.

Consider something like

service.cal1().subscribe(val => {
  service.call2(val).subscribe( res => {
    *does things*
  }
}

What you are triggering is a new Subscription (and therefor a new executed pipe) for each an every value that get emited by the Observable of call1(). This can leave you with hundreds of unhandled Observables ans Subscriptions which all stay in memory for the time being.

You need to know that when you subscribe() to a Observable multiple times, your subscribers won't listen to the exact same source, instead they all trigger a new copy of your defined Observable pipeline.

As stated in the first example in the Observable Docu

Observable that pushes the values 1, 2, 3 immediately (synchronously) when subscribed

Emphasize mine

The Observable does nothing on its own but starts its whole journey whenever subscribed

That is why you would try to use something like switchMap() to change to the other call instead of leaving the original subscription as is.

Upvotes: 10

Adrian Brand
Adrian Brand

Reputation: 21638

let sub1, sub2, sub3, sub4;
sub1 = service.call1().subscribe(result1 => {
  sub2 = service.call2(result1).subscribe(result2 => {
    sub3 = service.call3(result2).subscribe(result3 => {
      sub4 = service.call4(result3).subscribe(result4 => {
        // Do stuff with result 4
      });
    });
  });
});

vs

let sub = service.call1().pipe(
  switchMap(result1 => service.call2(result1)),
  switchMap(result2 => service.call3(result2)),
  switchMap(result3 => service.call4(result3)),
  switchMap(result4 => service.call5(result4))
)

Upvotes: 5

Related Questions