Angular applications often rely on Observables for handling asynchronous operations, such as HTTP requests, user events, or real-time data streams. Managing the lifecycle of these subscriptions is crucial to prevent memory leaks and unexpected behavior, especially as components and services are created and destroyed.
One of the most effective tools for this in modern Angular is the takeUntilDestroyed operator, introduced in the @angular/core/rxjs-interop
package.
What is takeUntilDestroyed?
takeUntilDestroyed is an RxJS operator that automatically completes an Observable when the calling context (such as a component, directive, or service) is destroyed. This means you no longer need to manually unsubscribe from Observables in your ngOnDestroy lifecycle hook, takeUntilDestroyed handles it for you.
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({...})
export class MyComponent {
private someService = inject(SomeService);
constructor() {
this.someService.getData()
.pipe(takeUntilDestroyed())
.subscribe(data => {
// handle data
});
}
}
When the component is destroyed, the subscription is automatically cleaned up, preventing memory leaks and side effects from lingering subscriptions. This is especially important for Observables that emit multiple values over time, such as those from interval, Subject, or real-time data sources, as opposed to HTTP requests with HttpClient, which complete automatically after a single emission.
It does not mean you should not care about the unsubscription of HTTP Requests: Letting them live after the component destruction could lead to some side effects you want to avoid.
Usage outside of the injection content
If you need to use it outside of an injection context, you can inject a DestroyRef and pass it explicitly:
import { DestroyRef, inject } from '@angular/core';
export class MyComponent {
private someService = inject(SomeService);
private destroyRef = inject(DestroyRef);
getData() {
this.someService.getData()
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe();
}
}
Best practices
When data from your observable is meant to be used only in a template, prefer relying on the async pipe to subscribe. Angular will automatically clean the subscription when the component is destroyed.
Top comments (0)