DEV Community

Benjamin Arambide
Benjamin Arambide

Posted on

Simplify Observable Subscriptions in Angular with a Custom Destroyer Service

Simplify Observable Subscriptions in Angular with a Custom Destroyer Service

Managing observable subscriptions in Angular can be challenging, especially when it comes to ensuring that subscriptions are properly cleaned up to prevent memory leaks. One common approach is to use the takeUntil operator with a Subject that emits a value when the component is destroyed. This article will show you how to simplify this process by creating a custom Destroyer service that extends Subject.

Why Use takeUntil?

The takeUntil operator in RxJS allows you to automatically unsubscribe from an observable when another observable emits a value. This is particularly useful in Angular components where you want to unsubscribe from observables when the component is destroyed.

Creating the Destroyer Service

We will create a Destroyer class that extends Subject<void> and implements OnDestroy. This class will handle emitting a value and completing the subject when the component is destroyed.

Step 1: Create the Destroyer Class

First, create a service file called destroyer.service.ts and add the following code:

import { Injectable, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class Destroyer extends Subject<void> implements OnDestroy {
  ngOnDestroy() {
    this.next();
    this.complete();
  }
}
Enter fullscreen mode Exit fullscreen mode

In this class:

  • Destroyer extends Subject, which means it inherits all the functionality of a Subject.
  • It implements OnDestroy and overrides the ngOnDestroy method to call next() and complete(). This will emit a value and complete the subject when the component is destroyed.

Step 2: Use the Destroyer in a Component

Next, inject the Destroyer service into your component and use it with the takeUntil operator.

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Observable, of } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Destroyer } from './destroyer.service';

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.css'],
  providers: [Destroyer] // Ensure a unique instance per component
})
export class ExampleComponent implements OnInit, OnDestroy {
  data$: Observable<any>;

  constructor(private destroyer: Destroyer) {}

  ngOnInit() {
    this.data$ = of('example data').pipe(
      takeUntil(this.destroyer)
    );

    this.data$.subscribe(data => {
      console.log(data);
    });
  }

  ngOnDestroy() {
    // Destroyer will handle emitting destroy signal
  }
}
Enter fullscreen mode Exit fullscreen mode

In this component:

  • The Destroyer service is injected through the constructor.
  • In ngOnInit, takeUntil is used with this.destroyer to manage the lifecycle of the observable.
  • When the component is destroyed, the ngOnDestroy method of the Destroyer service is called, which emits a value and completes the subject, unsubscribing from the observable stream.

Conclusion

Using a custom Destroyer service in Angular simplifies the process of managing observable subscriptions. By extending Subject and implementing OnDestroy, we can create a reusable service that handles the cleanup of observables automatically. This approach reduces boilerplate code and helps prevent memory leaks in your Angular applications.

Feel free to use and modify the code provided in this article to suit your specific needs. Happy coding!

Top comments (0)