Unsubscribe from Angular Observables

True enough to make us all sad.

Juggling Observables inside of your Angular components can be a hefty task to manage once you have more than a couple. You might notice funky things in your application if you’re changing routes in a single page app without unsubscribing from your Observables. For example, you might notice that a console.log() debugging call is running twice (or more), depending on how many “open” subscriptions you have.

Consider this code (actually something I use live in one of my products) as an example of how I have overcome this challenge:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router } from '@angular/router';
import { DiscoveryService } from '../discovery.service';
import { UserService } from '../user.service';
import { WindowService } from '../window.service';
import 'rxjs/Rx';
@Component({
selector: 'ceqoo-discovery',
templateUrl: './discovery.component.html'
})
export class DiscoveryComponent implements OnInit, OnDestroy {
private subscriptions: any = [];
  constructor(
private _discoveryService:DiscoveryService,
private _userService: UserService,
private _windowService: WindowService,
private router:Router
) { }
  ngOnInit() {
this.subscriptions.push(
this._userService.loginChanged.subscribe(
value => {
// handling
}
)
);

this._userService.validateUser();
}
  ngOnDestroy() {
this.subscriptions.forEach(s => s.unsubscribe());
}
}

First thing we are doing here is importing the OnInit and OnDestroy methods from Angular core. This allows us to implement the named methods to do fancy things like begin our subscriptions after Angular first displays the data-bound properties and sets the directive/component’s input properties, and unsubscribe from them just before Angular destroys the directive/component. You should obviously be familiar with this if you’ve done any sort of Angular already:

import { Component, OnInit, OnDestroy } from '@angular/core';

Next, we are letting TypeScript know those methods are part of our Component, so we can implement them inside of our Component block. This is simply a matter of adding the implements syntax like so:

export class DiscoveryComponent implements OnInit, OnDestroy {
You, probably.

Now, we push our Observables onto the subscriptions[] array we have already defined, instead of simply subscribing. This way, we have a running record of what we’re subscribed to:

ngOnInit() {
this.subscriptions.push(
this._userService.loginChanged.subscribe(
value => {
// handling
}
)
);

this._userService.validateUser();
}

Optionally, you can also import the abstract class ISubscription from rxjs and define it as follows:

import { ISubscription } from "rxjs/Subscription";
// ..
private subscriptions: ISubscription;

Then, when we break down the Component and run ngOnDestroy(), we will unsubscribe from each of the Observables:

ngOnDestroy() {
this.subscriptions.forEach(s => s.unsubscribe());
}

I hope this helps you keep track of your Observables and unsubscribe from them easily. Do note that the AsyncPipe does not require this code (you will know if this applies to you).

Doubtful, since he called it Angular 2.
Show your support

Clapping shows how much you appreciated Domenic Merenda’s story.