How to clean-up Observables in Angular

Jacob Overgaard
IMPACT Developers
Published in
3 min readApr 30, 2019

Working with Observables from RxJS in Angular is really great, and it is also the default return type of built-in Angular services, like the HttpClient for instance, but how do you remove them from memory once they are done?

TLDR; at the bottom!

One thing to note when using Observables/Promises that are non-completing, unlike the HttpClient which always terminates on complete, is that they will leave a small footprint in memory if not dealt with accordingly. Sometimes you may want to have an Observable that lives for the entirety of the application cycle, like a state service, and that is a-ok! But if you create Observables that do not complete and are more specific to a component, you may want to consider destroying them during the OnDestroy life-cycle hook to save on memory and watchers. If you do this for HttpClient Observables, you have the added benefit of canceling the http request in the client browser entirely as well.

I found one pattern that I am applying to all my applications to destroy (or unsubscribe) Observables which is to use the takeUntil operator. This operator will — according to the docs — subscribe and begin mirroring the source Observable and will continue doing so until a second Observable emits a value or a ‘complete’ notification, which then leads to its own termination.

All of this means, if we create some kind of Observable, e.g. a Subject, and make that Subject emit a value when the component is destroyed, then we can terminate all of our Observables in one go without leaving any footprint in memory behind us.

Correct flow with more than one operator

If you have more than one pipeable operator in your Observable subscription, please be aware where to place the takeUntil operator in order to avoid subscription leaks. A rule of thumb is to place the operator last in the flow, according to this article.

TLDR; or if you came this far, here is the example.

If you have this:

@Component({
name: 'app-component'
})
export class AppComponent extends OnInit{
constructor(private http: HttpClient) {}
ngOnInit() {
this.http.get(url)
.subscribe(data => console.log(data));
}
}

Then remember to add the takeUntil operator to all your Observables with a new Subject that will itself also be completed in the OnDestroy hook:

@Component({
name: 'app-component'
})
export class AppComponent extends OnInit, OnDestroy {
private unsubscribe = new Subject<void>();
constructor(private http: HttpClient) {} ngOnInit() {
this.http.get(url)
.pipe(
takeUntil(this.unsubscribe)
)
.subscribe(data => console.log(data));
}
ngOnDestroy() {
// Emit something to stop all Observables
this.unsubscribe.next();
// Complete the notifying Observable to remove it
this.unsubscribe.complete();
}
}

Or use the async pipe directly in the template, which will automatically unsubscribe from the source Observable during the OnDestroy hook:

@Component({
name: 'app-component'
template: `
<div *ngFor="let item of listService.get() | async">Item</div>
`
})
export class AppComponent {
constructor(public listService: ListService) {}
}

--

--