Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do we have to unsubscribe when using switchMap operator in rxjs in Angular 2?

Tags:

angular

rxjs

In Angular 2 there are some observables that you do not need to unsubscribe from. For example http requests and activatedRoute.params.

Angular/RxJs When should I unsubscribe from `Subscription`

But what happens when I use switchMap on for example activatedRoute.params and inside that switchMap I access a service that returns an observable that would need to be unsubscribed if subscribed to in the usual way.

Something like this:

this.activatedRoute.params
    .switchMap((params: Params) => this.userService.getUser(+params['id']))
    .subscribe((user: User) => this.user = user);

If I called this.userService without the switchMap and without activatedRoute.params I would have to unsubscribe from it.

// userService.getUser() takes in optional id?: number.
this.subscription = this.userService.getUser().subscribe(
    (user: User) => {
        this.user = user;
    }
 );

And then later..

this.subscription.unsubscribe();

My question is, do I need to unsubscribe from activatedRoute.params if I use switchMap on it and call a service that would need to be unsubscribed otherwise?

like image 381
Alex Avatar asked Jun 25 '17 17:06

Alex


People also ask

Does switchMap subscribe?

The SwitchMap creates a inner observable, subscribes to it and emits its value as observable.

How does switchMap work in RxJS?

Once the higher-order observable emits a new value, switchMap executes the function to get a new inner observable stream and switches the streams. It unsubscribes from the current stream and subscribes to the new inner observable. The operator works in the following way: Subscribe to a higher-order source observable.

Do we need to unsubscribe observable in Angular?

No need to unsubscribe from internal observables of an application scoped service since this service never get's destroyed, unless your entire application get's destroyed, there is no real reason to unsubscribe from it and there is no chance of memory leaks.

Do I need to unsubscribe from observable?

In Angular applications, it's always recommended to unsubscribe the observables to gain benefits like: Avoids Memory Leaks. Aborting HTTP requests to avoid unwanted calls.


2 Answers

If the source observable to which you are subscribing always completes or errors, you don't need to unsubscribe.

However, if you compose another observable from the source using switchMap, whether or not you need to unsubscribe depends upon the observable returned within switchMap. If the returned observable does not always complete or error, then, yes, you will need to unsubscribe.

If the source errors, an automatic unsubscription will occur:

const source = new Rx.Subject();
const composed = source.switchMap(() => Rx.Observable.interval(200));

composed.subscribe(value => console.log(value));
source.next(1);

setTimeout(() => {
  console.log("Erroring...");
  source.error(new Error("Boom!"));
}, 1000);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://unpkg.com/[email protected]/bundles/Rx.min.js"></script>

However, if the source completes, an automatic unsubscription will not occur:

const source = new Rx.Subject();
const composed = source.switchMap(() => Rx.Observable.interval(200));

composed.subscribe(value => console.log(value));
source.next(1);

setTimeout(() => {
  console.log("Completing...");
  source.complete();
}, 1000);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://unpkg.com/[email protected]/bundles/Rx.min.js"></script>
like image 140
cartant Avatar answered Oct 07 '22 05:10

cartant


switchMap creates a link between the previous and new observable. If you change the first observable, the second will be always be triggered.

Anything subscribed after the switchMap will be hearing changes on both, the initial observable and the returned observable.

To fully stop the first observable to update the second one or the rest is by using take, takeUntil, or takeWhile. Like:

const howTimerWorks = interval(5000).pipe(
  take(2), // only get 2 responses after 5 seconds each
  switchMap(initialNumber => interval(1000)));

// 0 after 5s, then 1, 2 , 3, (new Subs) 0, 1, ... every sec, forever now.
howTimerWorks.subscribe(console.log)

like image 1
Ignacio Bustos Avatar answered Oct 07 '22 05:10

Ignacio Bustos