How to unsubscribe RxJs Observable in Angular

Each time you call subscribe method on RxJs Observable, you should (most of the time) also call unsubscribe. See how you can do it in Angular components.

October 2, 2022 angular angular-15

Unsubscribe on ngOnDestroy hook

Advantages:

  • simplicity,
  • can unsubscribe individually.

Disadvantages:

  • boilerplate code,
  • a potential problem with the initial value (not null safety),
  • need to manually unsubscribe.
@Component({})
export class MyComponent implements OnInit, OnDestroy {
private sub1!: Subscription;
private sub2!: Subscription;
ngOnInit(): void {
this.sub1 = interval(1000).subscribe();
this.sub2 = interval(1000).subscribe();
}
ngOnDestroy(): void {
this.sub1.unsubscribe();
this.sub2.unsubscribe();
}
}

Unsubscribe on ngOnDestroy hook with subscriptions container

Advantages:

  • simplicity,
  • null safety,
  • need to unsubscribe always only once.

Disadvantages:

  • boilerplate code,
  • need to manually unsubscribe.
@Component({})
export class MyComponent implements OnInit, OnDestroy {
private subs = new Subscription();
ngOnInit(): void {
const sub1 = interval(1000).subscribe();
const sub2 = interval(1000).subscribe();
this.subs.add(sub1);
this.subs.add(sub2);
}
ngOnDestroy(): void {
this.subs.unsubscribe();
}
}

Unsubscribe with async pipe

Advantages:

  • no need to implement OnInit and OnDestroy interfaces, async pipe does it automatically,
  • independent of change detection strategy if data from a stream are used within a template.

Disadvantages:

  • less performance (async is not a pure pipe) with comparison to subscribe in component logic.
@Component({
template: `
<ng-container *ngIf="interval1$ | async"></ng-container>
<ng-container *ngIf="interval2$ | async"></ng-container>
`,
})
export class MyComponent {
interval1$ = interval(1000);
interval2$ = interval(1000);
}

Complete stream with takeUnitl operator

Advantages:

  • simplicity,
  • null safety,
  • calling next on destroy$ causes complete on all streams.

Disadvantages:

  • need to manually unsubscribe.
@Component({})
export class MyComponent implements OnInit, OnDestroy {
private destroy$ = new Subject<void>();
ngOnInit(): void {
interval(1000).pipe(takeUntil(this.destroy$)).subscribe();
interval(1000).pipe(takeUntil(this.destroy$)).subscribe();
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
}

Unsubscribe/Complete with destroyable local service

Thanks to destroyable local service you can move unsubscribe logic outside the component.

Advantages:

  • automatically unsubscribe, no need to implement OnInit and OnDestroy interfaces,
  • unsubscribe logic is handled in one place,
  • the single-responsibility principle is preserved,
  • BONUS: you can handle unsubscribe and takeUntil pattern in one place

Disadvantages:

  • the component has an additional provider.
@Injectable()
export class Unsubscriber extends Subject<void> implements OnDestroy {
private subs = new Subscription();
set add(sub: Subscription) {
this.subs.add(sub);
}
ngOnDestroy(): void {
this.next();
this.complete();
this.subs.unsubscribe();
}
}
@Component({
providers: [Unsubscriber],
})
export class MyComponent implements OnInit {
constructor(private unsubscriber: Unsubscriber) {}
ngOnInit(): void {
// with takeUntil pattern
interval(1000).pipe(takeUntil(this.unsubscriber)).subscribe();
// with unsubscribe pattern
this.unsubscriber.add = interval(1000).subscribe();
}
}

Do you like the content?

Your support helps me continue my work. Please consider making a donation.

Donations are accepted through PayPal or Stripe. You do not need a account to donate. All major credit cards are accepted.

Portrait of the author

About me

On a daily basis, I work as a Front-End Developer with a primary focus on JavaScript. I feel most comfortable with Angular and NestJS, but I’m always eager to venture beyond a single tech stack. I effectively leverage AI tools in my workflow, which allows me to quickly onboard into new technologies and write code in other languages or frameworks whenever needed.

After hours, I bring my passion for tech into the physical world. I run my own homelab, where I experiment with server management and build home automation and monitoring powered by Home Assistant.

Leave a comment