Yet another way to handle RxJS subscriptions

Wojciech Trawiński
Oct 5 · 5 min read

Using the RxJS library means dealing with observables on a regular basis. You must have heard the following cliche hundreds of times:

If you subscribe to an observable, you need to take care of unsubscribing when you’re no longer interested in receiving notifications, otherwise you will create a memory leak.

There’re already several common techniques/approaches to handle the problem, however I’d like to introduce you to yet another one 🆕 in this blog post .


State of art

For the time being, you can pick one of the following solutions:

Dealing with subscriptions on your own

You can simply subscribe to an observable and keep a reference to the subscription under a class field. In the ngOnDestroy lifecycle hook method you need to call the unsubscribe method for all Subscription instances.

Advantages 🔼:

  • the easiest to understand solution for newbies,

Disadvantages 🔽:

  • hard to maintain for large number of subscriptions,

Using add method of a Subscription instance

You can create a parent Subscription instance and add child subscriptions to it using the add method. Although it’s simple and straightforward solution, it’s not well known.

Advantages 🔼:

  • keep multiple subscriptions under a single class field,

Disadvantages 🔽:

  • easy to forget implementing the ngOnDestroy method.

You can also take a similar approach and store subscriptions in an array and further call the forEach method in the ngOnDestroy method, however there’s no point in reinventing the wheel. In addition, there is a SubSink solution available.

Using decorators

Another way to mange subscriptions is to use a third-party solution based on decorators. The most popular is the AutoUnsubscribe. You simply subscribe and assign a Subscription instance to a class field. The decorator takes care of calling the unsubscribe method for all Subscription instances when the ngOnDestroy method is invoked for a component.

Advantages 🔼:

  • no need to unsubscribe on your own,

Disadvantages 🔽:

  • additional dependency,

Using Async Pipe in Angular

This is my favorite solution when it comes to dealing with the RxJS in an Angular application. Since most of the times you subscribe in order to get data for a view to render, you can subscribe implicitly at the view level. The Async Pipe takes care of unsubscribing when a component gets destroyed, therefore you will not get into memory leak troubles.

Advantages 🔼:

  • no need to subscribe explicitly, therefore not need to unsubscribe,

Disadvantages 🔽:

  • harder to access emitted values in a component’s methods.

Make OOP great again

So I’ve come up with another imperative solution which allows you to keep data emitted by an observable in a class field and helps you to avoid memory leaks.

The idea is to make use of inheritance and simply expose a single protected method for concrete classes extending the abstract one. More precisely two protected methods, but I’ll explain it in a moment:

As you can see the abstract class is responsible for subscribing to an observable and keeps the resulting Subscription object in its private store. I simply make us of a single parent Subscription instance and add child subscriptions to it, but you could take different approaches as well, namely array-based or using the SubSink third-party class. When a component which extends the abstract class gets destroyed, the ngOnDestroy method from the abstract class is invoked and all the subscriptions are cancelled.

Let’s see it in action:

In the above component I simply make use of inheritance in order to get the subscribe method from the base class. You can test the solution, since I provide a link to the example at the end of the blog post.

The counter component doesn’t keep reference to the underlying subscription, since it’s desired to keep the subscription alive until it gets destroyed. However, there’re situations when you need to be able to cancel some subscriptions on demand. Therefore, you need to keep a reference to it in order to call the unsubscribe method for a given subscription when needed. The WithSubscription base class takes the scenario into account and returns a reference to the underlying Subscription instance from the subscribe method. Then, in order to unsubscribe on demand, you simply need to call the base class unsubscribe method and pass a reference to an appropriate Subscription instance:

Note that keeping a reference to the Subscription instance is only needed if you want to be able to cancel it on demand.

Advantages:

  • no need to unsubscribe (explicitly in your code),

Disadvantages:

  • need to extend the base class,

Conclusions

In this blog post I presented another alternative to mange the RxJS subscriptions in an imperative way. Although my first choice will always be the Async Pipe based approach, I agree that for some people it can be initially difficult to think in a reactive way and they may prefer to follow the imperative solutions. If you want an in-depth comparison I highly encourage you to take a look at this great blog post by Tomas Trajan. In addition, you don’t always use the RxJS together with Angular. Feel free to play around with the example:

I hope you liked the post and learned something new 👍 If so, please give me some applause 👏

JavaScript everyday

Improve your JavaScript skills everyday!

Wojciech Trawiński

Written by

Doing awesome things using JavaScript

JavaScript everyday

Improve your JavaScript skills everyday!

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