My favourite unsubscribe pattern is to use takeUntil
. takeUntil()
accepts an observable, and will stop the subscription when that observable emits a value.
The long-winded way to do this is emit a value in ngOnDestroy()
.
destroyed = new Subject<void>();
ngOnInit(): void {
myService.getData().pipe(
takeUntil(this.destroyed)
).subscribe(data => {
// process data
});
}
ngOnDestroy(): void {
this.destroyed.next();
this.destroyed.complete();
}
This gets quite tedious once you've done this a few times. The best solution I've seen for this (and currently use) is to set up a shared function that emits the destroyed value for you. Source Credit
import { OnDestroy } from '@angular/core';
import { ReplaySubject, Subject, Observable } from 'rxjs';
export function componentDestroyed(component: OnDestroy): Observable<void> {
const oldNgOnDestroy: () => void = component.ngOnDestroy;
const destroyed: Subject<void> = new ReplaySubject<void>(1);
component.ngOnDestroy = () => {
oldNgOnDestroy.apply(component);
destroyed.next(undefined);
destroyed.complete();
};
return destroyed.asObservable();
}
It is then almost trivial to use in your component:
ngOnInit(): void {
myService.getData().pipe(
takeUntil(componentDestroyed(this))
).subscribe(data => {
// process data
});
}
ngOnDestroy(): void {}
All you have to do is implement ngOnDestroy in your component and add takeUntil(componentDestroyed(this))
to your pipe.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…