Skip to content

Instantly share code, notes, and snippets.

@SimGus
Last active January 13, 2020 21:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SimGus/2b1a9e83ab0e4922936931f6702d97e6 to your computer and use it in GitHub Desktop.
Save SimGus/2b1a9e83ab0e4922936931f6702d97e6 to your computer and use it in GitHub Desktop.
Observable unsubscribing inside Angular components
////////////////////////////////////////////////////////////////////////////////////////////
// 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