Angular Unsubscribe Manager — Simplifying Cleanup

Pratiyush Prakash
Dev Genius
Published in
3 min readFeb 11, 2024

--

Angular developers are no strangers to the power and versatility of observables, especially when dealing with asynchronous operations. However, with great power comes great responsibility, and one critical responsibility is managing subscription to prevent memory leaks. In this article we will create our own Unsubscribe manager which will simplify the process of cleaning up subscriptions and ensures a more robust and efficient Angular application.

Photo by Gary Chan on Unsplash

The importance of subscription management

Angular relies heavily on observables for handling asynchronous operations, such as HTTP requests or user integrations. However, failing to properly manage these subscriptions can lead to memory leaks, degraded performance, and unexpected behavior. Manual subscription handling is error-prone and can be tedious, especially in larger codebases.

Solution: A Unified Unsubscriber manager class

We can create a dedicated Unsubscriber class. By extending this class and channeling all subscriptions through it, we can simplify the unsubscription process and minimize chances of overlooking critical cleanup steps.

Implementation

This class offers a method for adding single or multiple subscriptions. During component’s destruction lifecycle hook, it goes through all subscriptions, ensuring each one is unsubscribed.

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

/**
* Class which each component can extend to unsubscribe the
* subscriptions when component is destroyed.
*
* Usage:
* ~~~~~~
*
* 1. Create components from subclassing Unsubscriber.
*
* Example:
* // extending
* class SampleComponent extends Unsubscriber {}
*
* // add subscriptions
* this.addSubscription(subscription);
*
* // Don't worry about unsubscriptions. It is handled for you.
* // If you implement ngOnDestroy, call super.ngOnDestroy().
*
* 2. As an attribute in the components
*
* Example:
* // Creating an instance
* this.unsubscriber = Unsubscriber();
*
* // Add subscriptions
* this.unsubscriber.addSubscription(subscription);
*
* // Remove subscriptions
* ngOnDestroy() {
* this.unsubscriber.unsubscribe();
* }
*
* @export
* @class Unsubscriber
* @implements {OnDestroy}
*/
@Injectable()
export class Unsubscriber implements OnDestroy {
private subscriptions: Subscription[] = [];

addSubscription(subscription: Subscription | Subscription[]) {
if (Array.isArray(subscription)) {
this.subscriptions.push(...subscription);
} else {
this.subscriptions.push(subscription);
}
}

unsubscribe() {
this.subscriptions
.filter(subscription => subscription)
.forEach(subscription => {
subscription.unsubscribe();
});
}

ngOnDestroy() {
this.unsubscribe();
}
}

Using the Unsubscriber class in any Component or Service.

import { Component, OnInit } from '@angular/core';
import { Unsubscriber } from 'path-to-your-unsubscriber-class';
import { SomeService } from 'path-to-your-service';

@Component({
selector: 'app-demo',
templateUrl: './demo.component.html',
styleUrls: ['./demo.component.css']
})
export class CompetitorRequestTableComponent
extends Unsubscriber
implements OnInit
{
constructor(
private someService: SomeService
) {
// This is importand step to instantiate
super();
}

ngOnInit(): void {
// You can add an array of subscription or even a single subscription
this.addSubscription(
this.someService.getData().subscribe(() => {
// do your things
})
);
}

}

To sum up, Unsubscribe manager simplifies subscription cleanup, mitigates the risk of memory leaks, and enhance overall performance of Angular application. By adopting this approach, developers can write more robust and maintainable code, focusing on building features rather than worrying about manual subscription management.

--

--

Full stack Dev and Lead @ Texas Instruments. Follow me for short articles on software development.