Avoiding nesting subscriptions in Angular 2+?
Avoiding nested subscriptions depends on the nature of the observables and how they depend on each other:
Co-dependent observables
When an observable (this.grants.get()
) depends on the notification from another observable (this.user
), you could use any of the RxJS higher order mapping operators switchMap
, mergeMap
, concatMap
and exhaustMap
. Each has their own purpose. You could find the differences between them here.
Brief differences b/n them
-
switchMap
- cancel inner observable if the outer observable emits -
mergeMap
- trigger inner observable for each outer notification (flatten the outer notifications) -
concatMap
- essentiallymergeMap
with single concurrent request at any time (flattens the outer notifications but emit them in order) -
exhaustMap
- ignore outer notifications if inner observable hasn't completed
Illustration using switchMap
operator
this.user.pipe(
switchMap(e => this.grants.get(e))
).subscribe((x) => {
console.log(x)
});
Independent observables
If the observables are independent of each other, you could use RxJS functions like forkJoin
, combineLatest
or zip
to trigger the observables in parallel.
Brief differences b/n them
-
forkJoin
α - emit only when all the observables complete -
combineLatest
α,β - emit when any of the observables emit (observables w/o emissions will emit old value) -
zip
α,β - emit when all of the observables emit
Illustration using forkJoin
forkJoin(this.obs1, this.obs2, ...).subscribe(
res => console.log(res)
);
α - emits an array of notifications from each observable (eg. (this.obs1, this.obs2, ...)
will emit ['res from obs1', 'res from obs2', ...]
).
β - all observables should emit atleast once for the operator to emit