DEV Community

Cover image for Efficiently Destroying Observables in Angular
David
David

Posted on

Efficiently Destroying Observables in Angular

Managing subscriptions to observables is crucial when working with Angular to prevent memory leaks and ensure the application remains performant. A common mistake developers make (myself included - that is why I'm doing this post) is failing to unsubscribe from observables when a component is destroyed. This blog post will guide you through an efficient way to handle this using Angular's ngOnDestroy lifecycle hook and the takeUntil operator from RxJS.

Why Do You Need to Unsubscribe?

When you subscribe to an observable, it continues to emit values indefinitely unless it completes or you explicitly unsubscribe. If you don't unsubscribe—especially in components that are frequently created and destroyed—you risk memory leaks and unintended behavior, as these observables will keep running in the background even after the component is gone.

The Solution: takeUntil and ngOnDestroy

The takeUntil operator allows you to automatically unsubscribe from observables when a certain condition is met. By combining this with Angular's ngOnDestroy lifecycle hook, you can ensure that all subscriptions are properly cleaned up when the component is destroyed.

Step-by-Step Implementation

  • Import Necessary Modules: Import Subject from rxjs and takeUntil from rxjs/operators.
  • Create a Subject to Act as a Notifier: This subject will emit a value when the component is destroyed.
  • Use the takeUntil Operator in Your Subscriptions: This ensures that the subscription is automatically unsubscribed when the notifier emits a value.
  • Trigger the Notifier in ngOnDestroy: When the component is destroyed, emit a value from the notifier and complete it.
import { Component, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

@Component({
  selector: 'app-sample',
  templateUrl: './modal-material.component.html',
  styleUrls: ['./modal-material.component.css']
})
export class SampleComponent implements OnDestroy {
  private destroy$ = new Subject<void>();

  initializeForm(): void {
    const request: SomeRequest = { /* request data */ };
    this.service.create(request)
      .pipe(takeUntil(this.destroy$))
      .subscribe(
        () => this.finish(),
        error => this.finish(error)
      );
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }
}
Enter fullscreen mode Exit fullscreen mode

Key points:

  • destroy$ Subject: This subject will emit a value when the component is destroyed, signaling all subscriptions to complete.
  • takeUntil(this.destroy$): This operator ensures that the subscription is automatically unsubscribed when the destroy$ subject emits a value.
  • ngOnDestroy Lifecycle Hook: When the component is destroyed, the destroy$ subject emits a value and completes, effectively cleaning up all subscriptions that use takeUntil(this.destroy$).

Conclusion

By using the takeUntil operator in combination with the ngOnDestroy lifecycle hook, you can efficiently manage your subscriptions and prevent memory leaks in your Angular applications. This approach ensures that all observables are properly destroyed when the component is no longer needed, keeping your application performant and bug-free.

Implement this pattern in your Angular projects to ensure clean and efficient resource management, leading to a smoother and more reliable user experience. Happy coding!

Top comments (1)

Collapse
 
mthood profile image
mthood • Edited

hi, i use takeuntildestroyed() that simplify all things. This approach in obsolete is my projects. Thanks,