Skip to content

How to auto-unsubscribe in Angular component classes with Ivy.

Notifications You must be signed in to change notification settings

kaplan81/auto-unsubscribe-ng9

Repository files navigation

How to unsubscribe in Angular 9

Up and running

npm i
npm start

Navigate to http://localhost:4200/. The app will automatically reload if you change any of the source files.

Freezer, the destroyer of components

Once you load the app in your browser you should see something like this:

There is a service implemented that checks whether DevTools is open or not. You need it open in order to test the destruction and consequent unsubscription of components that were previously subscribed to observables.

Click on OK and open DevTools console. Now you should see the emission of a counter every second:

If you click on PUSH TO DESTROY Freezer will take care of destroying the current component by navigating to a DestroyedComponent.

As you can see the count stops. That means that our observable was unsubscribed. Also this.subscription$$.closed outputs true. That means that we included an extra action to check on the subscription$$ inside the ngOnDestroy() method.

import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core';
import { interval, Observable, Subject, Subscription } from 'rxjs';
import { takeUntil, tap } from 'rxjs/operators';

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  templateUrl: './boilerplate.component.html',
})
export class BoilerplateComponent implements OnInit, OnDestroy {
  destroyed$ = new Subject<void>();
  observable$: Observable<number> = interval(1000);
  subscription$$: Subscription;

  ngOnInit(): void {
    this.subscription$$ = this.observable$
      .pipe(tap(console.log), takeUntil(this.destroyed$))
      .subscribe();
  }

  ngOnDestroy(): void {
    this.destroyed$.next();
    // Any extra actions:
    console.log('this.subscription$$.closed in ngOnDestroy:::', this.subscription$$.closed);
  }
}

How to remove the boilerplate

Our goal is removing these 3 things from any component class of our project:

  • destroyed$ = new Subject<void>();
  • this.destroyed$.next();
  • ngOnDestroy(): void {}

In order to do that we can follow 4 different strategies in Angular.

  • Abstract class
  • Mixin class
  • Method decorator
  • Unsubscriber higher-order component.

You can find a detailed description on how to implement those in these 2 articles:

But they are already implemented for you in the current project.

How to test

You can click on the different navigation links located at the sidenav. On each one of them Freezer will destroy the corresponding component when clicking on PUSH TO DESTROY.

If you see the counter stopped it means that the observable was properly unsubscribed on destroy.

If you see the this.subscription$$.closed log it means that the strategy was not capable of removing the ngOnDestroy(): void {} boilerplate.

But see what happens when trying to use the DECORATOR strategy. The observable does not get unsubscribed! So it does not work in Angular 9. However, it does work in Angular 8 but since that is an older version of the framework this approach does not seem to be the most reliable one.

Happy coding!

About

How to auto-unsubscribe in Angular component classes with Ivy.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published