Angular | Use Inheritance to Unsubscribe from Observables
A reuse method to unsubscribe from observables
Inheritance is a mighty tool for reusing code and easily maintaining software programs long term. Design Patterns like Template Method, Factory Method, or Bridge show how useful inheritance can be.
There are lot of debates about preferring object composition over inheritance — from my point of view it depends which problems you want to solve or which people you try to help. In the example of this article we are using inheritance, and, of course, you could also solve it using object composition, too.
Usage of Observables in Angular
If you subscribe to Observables in Angular, a stream would be left open and a function callback would be called whenever values are emitted into it until the subscription is closed. If you do not close subscriptions, it could pose huge memory leaks and performance issues in your web application.
If you need to handle a lot of Observables in your application, writing the same structure of code in order to unsubscribe from these could become very annoying. Therefore, inheritance can be a great help.
Declaration of a superclass for reusability
A superclass is a class from which every subclass inherits the characteristics, attributes, and functions. In many programming languages it is also called parent class or base class.
To force a subclass to implement certain methods, you use abstract methods. Abstract methods are only declared in the superclass and have no implementation. With this you can force the subclasses to implement Angular’s lifecycle hook ngOnDestroy() to call the onDestroy() method of the base class. There, a last value emits and the Subject of RxJS gets completed.
import { Subject } from "rxjs";
import { Component } from "@angular/core";
@Component({
template: ""
})
export abstract class Unsubscribe {
protected onDestroy$ = new Subject<boolean>();
protected constructor() {
this.onDestroy$ = new Subject<boolean>();
}
public abstract ngOnDestroy(): void;
public onDestroy(): void {
this.onDestroy$.next(false);
this.onDestroy$.complete();
}
}
For normal classes Angular’s component decorator is not required and could be removed.
Superclass usage
Next, you can use the superclass in different Angular classes using the extends keyword. If you subscribe to any Observable type, you can use RxJS’s takeUntil operator, that emits the values emitted by the source Observable until the onDestroy$ Observable of the superclass emits a value. That happens when the onDestroy() function is called by Angular’s lifecycle hook ngOnDestroy().
import { Component, OnDestroy } from "@angular/core";
import { Unsubscribe } from "./unsubscribe.model";
import { interval, Observable, takeUntil } from "rxjs";
@Component({
template: ""
})
export class Observable1 extends Unsubscribe implements OnDestroy {
private _source: Observable<number> = interval(1000);
constructor() {
super();
}
public get source(): Observable<number> {
return this._source.pipe(takeUntil(this.onDestroy$))
}
public ngOnDestroy() {
this.onDestroy();
}
}
This is a small but efficient way to deal with observables and their subscriptions.
Closing Thoughts
Inheritance is a powerful tool alongside object composition. Often you have to choose one and the second seems to be the most decoupled one.
With this example I showed how to use inheritance in an effective way.
Follow me on Medium, or Twitter, or subscribe here on Medium to read more about DevOps, Agile & Development Principles, Angular and other useful stuff. Thanks for reading and hopefully you can use this article in the near future. Happy Coding! :)