How to avoid multiple subscription in Angular 2 component

2muchcoffee
Nov 26, 2016 · 3 min read

Preview448 words

I think every Angular 2 developer has faced the situation when there are too many subscriptions in the component. If you unsubscribe manually — you waist too much time and litter the code. If you forgot to do that — your application uses too many resources.

To simulate this situation let’s create the simple router, component and service:

@Injectable()
export class MyService {
name$ = new Subject();
}

Here we create 2 routes: test and home

export const ROUTES: Routes = [  
{ path: '', component: HomeComponent },
{ path: 'test', component: TestComponent }
];

and here we create the component

@Component({
...
})
export class TestComponent {
public subscribers: any = {};
constructor(public myService: AppState){
}
ngAfterViewInit() {
// The subscribe is made each time the view is uploaded
this.subscribers.name = this.myService.name$
.subscribe(name => {
console.log(name)
});
this.myService.name$.next('New Name Created');
}
}

In the added code we make the subscribe and type-out the name to console each time we reach subscribe.

If we will get across the route test several times we'll see that in console the name is typed-out many times. This is really not what we need (subscribe to Observable many times).

Let’s change our component to solve the problem:

// The modified component
@Component({
...
})
export class TestComponent {
public subscribers: any = {};
constructor(public myService: AppState){
}
ngAfterViewInit() {
this.subscribers.name = this.myService.name$
.subscribe(name => {
console.log(name)
});
this.myService.name$.next('New Name Created');
}
// Cleanup just before Angular destroys the directive/component.
// Unsubscribe observables and detach event handlers to avoid memory leaks.
ngOnDestroy(){
this.subscribers.name.unsubscribe();
}
}

After these changes, we’ll get what we expected in console — every time when getting to url ‘/test’ the name will be typed-out once.

But what will happen if we have 20 subscribes in the component? It’s really annoying — to unsubscribe from each Observables in every component.
To forget about unsubscribing — we can make a decorator. The main thing here is to save subscription in the variable this.subscribers, while the other job will be performed by decorator.

Let’s get it started:

// creating the decorator DestroySubscribers
export function DestroySubscribers() {
return function (target: any) {
// decorating the function ngOnDestroy
target.prototype.ngOnDestroy = ngOnDestroyDecorator(target.prototype.ngOnDestroy);
// decorator function
function ngOnDestroyDecorator(f) {
return function () {
// saving the result of ngOnDestroy performance to the variable superData
let superData = f ? f.apply(this, arguments) : null;
// unsubscribing
for (let subscriberKey in this.subscribers) {
let subscriber = this.subscribers[subscriberKey];
if (subscriber instanceof Subscriber) {
subscriber.unsubscribe();
}
}
// returning the result of ngOnDestroy performance
return superData;
}
}
// returning the decorated class
return target;
}
}

Now we can remove the ngOnDestroy from the component and include the decorator that will be doing the same thing.

@Component({
...
})
//here we apply the decorator
@DestroySubscribers()
export class TestComponent {
public subscribers: any = {};
constructor(public myService: AppState){
}
ngAfterViewInit() {
this.subscribers.name = this.myService.name$
.subscribe(name => {
console.log(name)
});
this.myService.name$.next('New Name Created');
}
}

The extended version of the decorator is available here: https://www.npmjs.com/package/ng2-destroy-subscribers

If your Angular2 application has many subscribers or you’re tired of wasting time to make a lot of same code — you can use this decorator.

You can find article here: http://blog.2muchcoffee.com/how-to-avoid-multiple-subscription-in-angular-2-component/

2muchcoffee

Written by

Web and Mobile App Development Company. Live and Breathe Angular and Rx.js. Open source contributors as the guarantee of product delivery. Enjoy your coffee ;)

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade