Last active
January 13, 2020 21:01
-
-
Save SimGus/2b1a9e83ab0e4922936931f6702d97e6 to your computer and use it in GitHub Desktop.
Observable unsubscribing inside Angular components
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//////////////////////////////////////////////////////////////////////////////////////////// | |
// In Angular, we often use *RxJS* observables. // | |
// // | |
// A frequent usecase of observables within Angular component is to have a subscription // | |
// to an observable for the whole lifetime of that component. // | |
// // | |
// To do this, we need to subscribe when the component comes up, // | |
// and we will *HAVE to* unsubscribe when the component is destroyed. // | |
// (Seriously, not unsubscribing will lead to memory leaking everytime the component gets // | |
// destroyed.) // | |
// // | |
// When we have several subscriptions, unsubscribing each subscription becomes cumbersome // | |
// and even risky -- you might forget to unsubscribe one of them and not realize it ever. // | |
// // | |
// In this gists, we show different solutions for that problem, ranging from the best one // | |
// to the least good (but still working and useful in some situations) one. // | |
//////////////////////////////////////////////////////////////////////////////////////////// | |
// In the examples below, we want to subscribe on the observables | |
// `observable1$` and `observable2$` for the whole lifetime of | |
// component `TheComponent`. | |
// The subscriptions are created during the `OnInit` method of the component, | |
// and are unsubscribed during the `OnDestroy`. | |
//=================== BEST SOLUTION =================== | |
// Let Angular manage the subscriptions/unsubscriptions | |
//--- the-component.component.ts --- | |
class TheComponent { | |
// nothing to do in here | |
} | |
//--- the-component.component.html --- | |
<html-tag>{{ observable1$ | async }}</html-tag> | |
<other-tag *ngIf="observable2$ | async"></other-tag> | |
//================== GOOD SOLUTION ==================== | |
// Use a subject to trigger the unsubscription | |
class TheComponent implements OnInit, OnDestroy { | |
private readonly destroy$ = new Subject(); | |
ngOnInit(): void { | |
observable1$.pipe( | |
takeUntil(destroy$), | |
).subscribe( | |
// ... | |
); | |
observable2$.pipe( | |
takeUntil(destroy$), | |
).subscribe( | |
// ... | |
); | |
} | |
ngOnDestroy(): void { | |
destroy$.next(); | |
destroy$.complete(); | |
} | |
} | |
//============= GOOD SOLUTION ================== | |
// Unsubscribe from all subscriptions at once | |
// (This solution is very clear, and thus maintainable.) | |
class TheComponent implements OnInit, OnDestroy { | |
private readonly subscriptions = new Subscription(); | |
ngOnInit(): void { | |
this.subscriptions.add( | |
observable1$.subscribe( | |
// ... | |
) | |
); | |
this.subscriptions.add( | |
observable2$.subscribe( | |
// ... | |
) | |
); | |
} | |
ngOnDestroy(): void { | |
subscriptions.unsubscribe(); | |
} | |
} | |
//=========== UGLY AND RISKY SOLUTION (problematic code) =============== | |
// Unsubscribe each solution individually | |
class TheComponent implements OnInit, OnDestroy { | |
private subscription1: Subscription; | |
private subscription2: Subscription; | |
ngOnInit(): void { | |
this.subscription1 = observable1$.subscribe( | |
// ... | |
); | |
this.subscription2 = observable2$.subscribe( | |
// ... | |
); | |
} | |
ngOnDestroy(): void { | |
this.subscription1.unsubscribe(); | |
this.subscription2.unsubscribe(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment