angularrxjsangular-routerrxjs-observablesangular-router-params

How properly subscribe to observable paramMap Angular?


I can get params from paramMap:

this.route.paramMap.subscribe((params: ParamMap) => {
  this.templateService.get(+params.get("id")!).subscribe((response: Json | JsonError) => {
    ...
  });
});

and also with the following way:

this.route.paramMap
  .pipe(
    switchMap((params: ParamMap) => this.templateService.get(+params.get('id')!))
  )
  .subscribe((response: Json | JsonError) => {
    ...
  });

But what's the difference? And what method is correct (or in other words what method match to what situations)?


Solution

  • There are several benefits of the switchMap() approach, compared to nested subscriptions:

    1. There is only one Subscription, which is easier to handle. For example, this allows moving the subscription to the template with the async pipe so you don't need to worry about change detection and unsubscribing.
    2. If you need to combine more than 2 Observables, nested subscriptions will lead to additional level of nesting per Observable, which makes the code harder to read.
    3. The switchMap() will automatically ignore emissions from the inner observable once a new outer value is emitted, which is quite hard to implement with nested subscriptions. This avoids a race condition which can happen in your example when a new param is pushed while the request from the templateService is still pending. With nested subscriptions, the pending request will be continued and the response will be processed, while with switchMap() the pending request will be ignored (and possibly even canceled).

    You can read more about switchMap() in the RxJS docs. So in general, nested subscriptions should be avoided, and switchMap() should be used instead.