user8743396
user8743396

Reputation:

Unsubscribing Multiple Subscription from Different Functions

i have multiple functions that have subscriptions. First i have it on the ngOnInit(), then i have another function called onSelectVillain(). So my question is this possible that you could just use this.subscription.unsubscribe(). Or should i make declare another subscription?

subscription: Subscription;

    ngOnInit() {
      this.subscription = this.heroService.getHeroes()
                       .subscribe(
                         heroes => this.heroes = heroes,
                         error =>  this.errorMessage = <any>error);
    }

    onSelectVillain(event) {
      this.subscription = this.villainService.getVillains()
                       .subscribe(
                         .....
    }

    ngOnDestroy(){
     this.subscription.unsubscribe()
    }

Upvotes: 1

Views: 2907

Answers (2)

Estus Flask
Estus Flask

Reputation: 222389

Once subscription value is replaced, previous subscription is lost, it's no different than any other value.

A cleaner way is to have different subscriptions that have meaningful names - heroesSubscription, villainsSubscription, etc:

heroesSubscription: Subscription;
villainsSubscription: Subscription;

ngOnInit() {
  this.heroesSubscription = this.heroService.getHeroes().subscribe(...);
}

onSelectVillain(event) {
  // possibly needs to unsubscribe previous subscription
  if (this.villainsSubscription)
    this.villainsSubscription.unsubscribe()

  this.villainsSubscription = this.villainService.getVillains().subscribe(...)
}

ngOnDestroy(){
 this.heroesSubscription.unsubscribe()
 this.villainsSubscription.unsubscribe()
}

If it's possible that onSelectVillain is called multiple times, previous subscription should be unsubscribed.

The code doesn't show the benefits of doing subscriptions manually. When observable values are consumed only in view, async pipe can be used instead because it does all subscription/unsubscription work automatically:

{{ heroService.getHeroes() | async }}

Upvotes: 1

Jay
Jay

Reputation: 175

It would be cleaner to use a seperate subscription - and if you use the same field you would never (manually) unsubscribe from the first subscription. Also if you don't want to clutter your component with lots of fields, that simply hold subscription references I would recommend to use a pattern, that involves using just one Subject, that is triggered at ngOnDestroy and before each subscribe you would use takeUntil. So your code could look like this:

private ngUnsubscribe = new Subject();

ngOnInit() {
  this.heroService.getHeroes()
                  .takeUntil(this.ngUnsubscribe)
                  .subscribe(
                     heroes => this.heroes = heroes,
                     error =>  this.errorMessage = <any>error);
}

onSelectVillain(event) {
  this.villainService.getVillains()
                     .takeUntil(this.ngUnsubscribe)
                     .subscribe(
                     .....
}

ngOnDestroy(){
    this.ngUnsubscribe.next();
    this.ngUnsubscribe.complete();
}

See this for further reference.

Note that subscriptions that are "finite", so where a complete state is called, don't neccessarily need to get unsubscribed manually. This is probably a good reference point for that.

Upvotes: 3

Related Questions