Is there a confirmed and elegant idiom of unsubscribing to all existing but possibly not initialized subscriptions in controller? Consider following snippet:
/* Somewhere on init */
if(/* condition 1 */) {
this.subscription1 = this.service1().subscribe();
}
if(/* condition 2 */) {
this.subscription2 = this.service2().subscribe();
}
And at cleanup phase:
onDestory() {
try{
this.subscription1.unsubscribe();
this.subscription2.unsubscribe();
} catch e {
/* One of subscriptions was uninitialized */
/* If that was first one, second may be left unsubscribed */
}
}
Basically there are for sure some of straight-forward methods like beloved ifology:
if(this.subscription1) {
this.subscription1.unsubscribe();
}
if(this.subscription2) {
this.subscription2.unsubscribe();
}
of using array of subscriptions instead of controller fields:
/* Somewhere on init */
if(/* condition 1 */) {
this.subscriptions.push(this.service1().subscribe())
}
if(/* condition 2 */) {
this.subscriptions.push(this.service2().subscribe())
}
noDestroy() {
this.subscriptions.forEach(s => s.unsubscribe();)
}
But maybe there are some neat and reliable ways of doing such task? According to my experience, ifology is tedious to conserve and easy to forget to update, while array-based makes your subscription list non-menagable in case you wish to selectively unsubscribe to selected subscription in other controller lifecycle moment than onDestroy
.
Why not use the takeUntil
RxJs operator?
You can subscribe to the observables you want, waiting for the takeUntil operator to unsubscribe from the Observable chain when another Observable emits:
You can declare your new Observable as a Subject:
private destroySubscriptions$ = new Subject<void>();
/* Somewhere on init */
if(/* condition 1 */) {
this.service1()
.pipe(
takeUntil(this.destroySubscriptions$)
).subscribe();
}
if(/* condition 2 */) {
this.service2()
.pipe(
takeUntil(this.destroySubscriptions$)
).subscribe();
}
And on the cleanup phase (typically on the onDestroy
Angular lifecycle hook):
ngOnDestroy() {
this.destroySubscriptions$.next();
}
Also, this is a recommendend pattern in RxJs to destroy your subscriptions! You can read more about the takeUntil
operator here.