8
votes

I have an Observable in my root (bootstrapped) Angular (6.x) component, AppComponent.
Normally, I would unsubscribe any open Subscription upon a destroy() call using the lifecycle hook, ngOnDestroy.
Since the AppComponent is the root of the application and therefore is never destroyed (except when the entire application is destroyed), do I still need to implement ngOnDestroy and do I need to bother with unsubscribing from my Subscriptions?

I haven't been able to find an answer to this, seemingly common, exact scenario.

Example:

export class AppComponent implements OnInit, OnDestroy {
  private tokenSubscription: Subscription;
  constructor(private dataSvc: DataService) { }
  ngOnInit() {
    this.tokenSubscription = this.dataSvc.myObservable.subscribe((val) => {
      // do stuff
    });
  }
  ngOnDestroy() {
    this.tokenSubscription.unsubscribe(); // Do I need this in root component?
  }
}

Thanks!

1

1 Answers

4
votes

One-time Subscriptions in AppComponent.ngOnInit() are Okay

RXJS subscriptions in the Angular AppComponent do not need to be unsubscribed, as long as the new Subscriptions are not being repeatedly created. It is fine, for example, if subscriptions are created in ngOnInit of AppComponent as long as they are one-time actions.

Angular Services provided in the Root should ideally be Singleton Services

For Angular services created in the root component, it is ideal to use singleton services to ensure that only one instance exists in the app.

Best Practices

Although it is generally okay to have subscriptions in the root component that are not unsubscribed, it is recommended to following best practices for managing subscriptions.

  • take(1) - for Subscriptions that only happen once during application startup, use RXJS take(1) operator, which has the benefit of automatically unsubscribing.
  • async Pipe - handles RXJS subscriptions behind the scenes and automatically unsubscribes.

Example using take(1)

constructor(private dataSvc: DataService) { }

ngOnInit() {
  this.dataSvc.myObservable.pipe(take(1)).subscribe((val) => {
    // do stuff
  });
}

See The Best Way To Unsubscribe RxJS Observables In The Angular Applications!