Chris Straw
SHARE:

Angular 16 takeUntilDestroy operator

The OG takeUntil from RxJS

The takeUntil operator from RxJS is frequently used in Angular applications to automatically unsubscribe from observables when a component is destroyed, thereby preventing memory leaks. Here’s how it is usually used:


import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

export class MyComponent implements OnDestroy {
  private onDestroy = new Subject<void>();

  constructor(private myService: MyService) {
    this.myService.getData()
    .pipe(takeUntil(this.onDestroy))
    .subscribe(data => console.log(data));
  }

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

In this example, takeUntil(this.onDestroy) ensures that the subscription to this.myService.getData() is automatically unsubscribed when the component is destroyed. This is achieved by emitting a value from onDestroy in the ngOnDestroy lifecycle hook, which causes the takeUntil operator to complete the subscription.

takeUntilDestroyed operator

The takeUntilDestroy operator was added by the Angular team in Angular 16. This simplifies the need to have an onDestroy Subject and the ngOnDestroy interface on the component.

Here is an example:

import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

export class MyComponent {

  constructor(private service: DataService) {
    this.service.getData()
      .pipe(takeUntilDestroyed())
      .subscribe(data => console.log(data));
  }
}

Passing OnDestroy reference

The takeUntilDestroyed operator can take a reference to the DestroyRef of the dependent/child observable.

Here is an example implementation:

import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

export class MyComponent implements OnInit {
  private destroyRef = inject(DestroyRef);

  ngOnInit() {
    interval(1000).pipe(
      takeUntilDestroyed(this.destroyRef)
    ).subscribe(console.log);
  }
}