Managing your RxJS Observable subscriptions in Angular with SubSink
RxJS and Observables are HOT in Angular now. Many of us have started using them and they are not too difficult to pick up and begin using. But there is probably a small piece you are forgetting...Unsubscribing to your subscriptions.
Way too often I open up an Angular Component and inside the ngOnInit() I see a subscription that is never being unsubscribed from. Something like this:
1 ngOnInit() { 2 this.userService.getAllUsers().subscribe(data => { 3 this.userList = data; 4 this.userListSubject$.next(this.userList); 5 }); 6 }
Above we have our userService, and we are subscribing to the GetAllUsers method in our service. But we never assign our call to any variable. This is an easy way to know we are never unsubscribing from this call.
Now you may have many calls like this in your app and it works fine. You don't notice any ill effects. But this is bad practice. If we subscribe we need to unsubscribe. We should not leave subscriptions laying around. We don't want to leave tons of open subscriptions. So what should the above code look like?
1 sub: Subscription; 2 3 ngOnInit() { 4 this.sub = this.userService.getAllUsers().subscribe(data => { 5 this.userList = data; 6 this.userListSubject$.next(this.userList); 7 }); 8 } 9 10 ngOnDestroy() { 11 this.sub.unsubscribe(); 12 }
Above, we created our sub variable to hold onto the subscription. And in the ngOnDestroy lifecycle hook, we unsubscribe. This looks pretty easy. Just a few extra lines of code. But what if we had lots of subscriptions. Having to add many new component level variables can clutter up our file quickly. And we already have a hard time remembering to unsubscribe, is their an easier way?
This is where the package SubSink developed by Ward Bell comes in. Managing subscriptions should not be difficult and SubSink makes it easy. The same code above using SubSink would look like.
1 private subscriptions = new SubSink(); 2 3 ngOnInit() { 4 // Method 1 5 this.subscriptions.add(this.userService.getAllUsers().subscribe(data => { 6 this.userList = data; 7 this.userListSubject$.next(this.userList); 8 })); 9 10 // Method 2 11 this.subscriptions.sink = this.userService.getAllUsers().subscribe(data => { 12 this.userList = data; 13 this.userListSubject$.next(this.userList); 14 }); 15 } 16 17 ngOnDestroy() { 18 this.subscriptions.unsubscribe(); 19 }
There are two easy ways we can use SubSink shown above. In Method 1 we directly add our subscription. While in Method 2 we are using a setter to add the subscription to the sink. Both end up doing the same thing functionally but we can use either syntax.
In the ngOnDestroy, we have one simple this.subscriptions.unsubscribe() call that does all the unsubscribing to all of our subscriptions for us. SubSink makes it much easier to manage our subscriptions and gives us no excuse to not remember to unsubscribe from them.
SubSink makes our lives easier managing the subscriptions for us. Making our code easier and less cluttered is always a big win!
If you are an Angular developer check out my post on Must-have VS Code Extensions for Angular Developers!