Search code examples
angularrxjs

Is there any other methods when using unsubscribe from `Subscription` in Angular/RxJS


Whenever I store the Subscription instances, I am using unsubscribe() during the ngOnDestroy life cycle in all components. But I want to implement that within one file, so I don't have to use unsubscribe() in each component.


Solution

  • As already said, takeUntilDestroyed is the most idiomatic way forward.

    However, in my company we are using a base class for all components and services that need to handle unsubscribe on destroy. I still find it simpler, with less magic involved.

    import { Injectable, OnDestroy } from '@angular/core';
    import { Observable, ReplaySubject } from 'rxjs';
    
    @Injectable()
    export class AutoUnsubscribe implements OnDestroy {
      readonly autoUnsubscriber: Observable<void> = new ReplaySubject<void>(1);
    
      ngOnDestroy() {
        if ((this.autoUnsubscriber as ReplaySubject<void>).closed) return;
        (this.autoUnsubscriber as ReplaySubject<void>).next();
        (this.autoUnsubscriber as ReplaySubject<void>).complete();
      }
    }
    

    Then, you can make your components, directives or services inherit from AutoUnsubscribe, and use everywhere the takeUntil RxJS operator:

    @Component({...})
    export class MyComponent extends AutoUnsubscribe {
      constructor(someService: MyService) {
        super();
        
        someService.getSome$().pipe(
          takeUntil(this.autoUnsubscriber)
        ).subscribe(data => { 
          // ...
        });
      }
    }
    

    It just becomes second nature, and you don't need to define the ngOnDestroy method, which AFAICT you should with takeUntilDestroyed.

    Every developer needs to just learn to check that a takeUntil is always the last operator in a pipe, just before the subscribe.

    This pattern removes also most of the benefits in using the async pipe, that is very often addressed as a very good and clean way to handle subscription, but in my experience is very prone to multiple subscription problems (like multiple calls to the same api).