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.
Source: Pixabay
There are many ways to unsubscribe observables in angular like using the async pipe|
,unsubscribe
, and thetake
and 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 tounsubscribe
your observables.
But what if we have multiple observables that we willunsubscribe
from?
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.takeUntil
withReplaySubject
.
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.
Screenshot of the sample web app by the author.
The search results are then displayed below the search boxes.
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 tosubscribe
to ourformControl
svalueChanges
observable.
Source code example on GitHub by the author.
The linethis.searchSubject$.next(searchString)
“emits” the signal to call the GitHub search API.
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>
TheGitHubService
class is given below:
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 thevalueChanges
observable.
Unsubscribe Each Observable
We will first assign our observable into aSubscription
property. Then we will unsubscribe using thatSubscription
property.
Here are ourClass
properties that hold the observables:
searchReposSub: Subscription;searchUsers: Subscription;
Initialize thevalueChanges
subscription in thengOnInit
method.
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 aSubscription
array:
subscriptions: Subscription[];
Push the subscribed observables into thesubscriptions
array property:
Source code example on GitHub by the author.
Unsubscribe by iterating through each subscription in thengOnDestroy
method:
this.subscriptions.forEach((subscription) => { subscription.unsubscribe();});
You can run the unsubscribe example in StackBlitz:
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 thetakeUntil
pipe.
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 thetakeUntil
pipe andReplaySubject
.
We will start by declaring ourReplaySubject
property:
private destroyed$: ReplaySubject<boolean> = new ReplaySubject(1);
ReplaySubject(n)
caches previousn
values emitted by the source observable. So we could use ourdestroyed$``ReplaySubject
to emit anunsubscribe
call inngOnDestroy()
.
ngOnDestroy() { this.destroyed$.next(true); this.destroyed$.unsubscribe();}
Our subscriptions will use thetakeUntil
operator.
In ourngOnInit
:
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 thetakeUntil
example in StackBlitz:
Running code example on StackBlitz by the author.
Conclusion
Try to avoid having tounsubscribe
manually whenever possible. This can be achieved by using async pipes|
, or any other RxJS operators liketake
andfirst
that 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 thetakeUntil
withReplaySubject
approach. You don’t have to keep track of your subscriptions with this approach. You’ll only need to declare yourReplaySubject
property. Then use that property tounsubscribe
.