Contents

How to Automatically Unsubscribe Multiple Observables in Angular

How to Automatically Unsubscribe Multiple Observables in Angular

Let’s use the power of async pipes and RxJS operators.

https://cdn-images-1.medium.com/max/800/1*Xrs5X2NR0GhMMEfZ34LbmA.jpeg

Source: Pixabay

There are many ways to unsubscribe observables in angular like using the async pipe|,unsubscribe, and thetakeand first operators.

I would normally default to using async pipes whenever possible so I don’t have to worry about unsubscribing. But there are situations where you can’t use async pipes and will have tounsubscribeyour observables.

But what if we have multiple observables that we willunsubscribefrom?

We could easily unsubscribe each of these observables but that will be a lot of boilerplate or repeated code.

However, we could minimize code duplication by using a declarative approach i.e.takeUntilwithReplaySubject.

Let’s dive into our examples:

Our Web App Example

Note that we can directly use async pipes in our web app example. Similar to theRest API examplein myprevious blog post. I’m using subscribe here as an example to illustrate the point of this blog post.

We have a web app with two GitHub search boxes, one for searching repositories and another to search for users.

https://cdn-images-1.medium.com/max/800/1*gA3m1HHieEs4LUVkqMnXcg.png Screenshot of the sample web app by the author.

The search results are then displayed below the search boxes.

https://cdn-images-1.medium.com/max/800/1*WseHud8u_BM96QJ4zUQ_cg.png Screenshot of the sample web app by the author.

Our web app will call the GitHub Search API after we enter a text in any of the search boxes. To achieve this, we need tosubscribeto ourformControlsvalueChangesobservable.

View Code on GitHub Gist

Source code example on GitHub by the author.

The linethis.searchSubject$.next(searchString)“emits” the signal to call the GitHub search API.

View Code on GitHub Gist

Source code example by the author.

Our results will be rendered in our template.

<div *ngFor="let result of results$ | async"> <div> <a [href]="result.html_url" target="_blank">{{ result.name || result.login }}</a> </div></div>

TheGitHubServiceclass is given below:

View Code on GitHub Gist

Source code example on GitHub by the author.

Now that we know what our sample web app is, let’s dig into how we are going to unsubscribe thevalueChangesobservable.

Unsubscribe Each Observable

We will first assign our observable into aSubscriptionproperty. Then we will unsubscribe using thatSubscriptionproperty.

Here are ourClassproperties that hold the observables:

searchReposSub: Subscription;searchUsers: Subscription;

Initialize thevalueChangessubscription in thengOnInitmethod.

View Code on GitHub Gist

Source code example on GitHub by the author.

Unsubscribe the observables individually throughngOnDestroy:

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

Or we can also unsubscribe each observable using aSubscriptionarray:

subscriptions: Subscription[];

Push the subscribed observables into thesubscriptionsarray property:

View Code on GitHub Gist

Source code example on GitHub by the author.

Unsubscribe by iterating through each subscription in thengOnDestroymethod:

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

You can run the unsubscribe example in StackBlitz:

View Live Demo

Running code example on StackBlitz by the author.

It’s much simpler to keep track of our subscriptions in one property array rather than multiple properties.

However, there is another approach that I prefer over using the subscription array — using thetakeUntilpipe.

Unsubscribe using takeUntil and ReplaySubject

This is a more declarative approach. We don’t have to keep track of the subscriptions in a class property if we advantage of thetakeUntilpipe andReplaySubject.

We will start by declaring ourReplaySubjectproperty:

private destroyed$: ReplaySubject<boolean> = new ReplaySubject(1);

ReplaySubject(n)caches previousnvalues emitted by the source observable. So we could use ourdestroyed$``ReplaySubjectto emit anunsubscribecall inngOnDestroy().

ngOnDestroy() { this.destroyed$.next(true); this.destroyed$.unsubscribe();}

Our subscriptions will use thetakeUntiloperator.

In ourngOnInit:

View Code on GitHub Gist

Source code example on GitHub by the author.

takeUntil(this.destroyed$)will keep emitting our source observable’s value until thedestroyed$observable emits a value. The source observable here isthis.searchReposFormControl.valueChanges.

You can run thetakeUntilexample in StackBlitz:

View Live Demo

Running code example on StackBlitz by the author.


Conclusion

Try to avoid having tounsubscribemanually whenever possible. This can be achieved by using async pipes|, or any other RxJS operators liketakeandfirstthat will automatically unsubscribe your observable under the hood.

But if you have no other choice than to useunsubscribe, like in the example we have above. Then go for thetakeUntilwithReplaySubjectapproach. You don’t have to keep track of your subscriptions with this approach. You’ll only need to declare yourReplaySubjectproperty. Then use that property tounsubscribe.