TypeScript - Angular abonnieren/abmelden Best Practices
Ich frage mich derzeit über Angular-Abonnements und deren Kündigung. Es gibt viele Informationen zu diesem Thema, daher bin ich ein wenig verloren in all dem.
Wann sollte ich mein Abonnement kündigen? Was passiert, wenn ich nie von ihnen kündige? Ich habe nie irgendwelche Fehler von Restabonnement bemerkt.
Gibt es eine Möglichkeit, sich in einer Komponente/App automatisch von allem abzumelden, sodass ich nicht für jede Subscription eine Eigenschaft deklarieren muss? Das kann sehr ärgerlich sein :
@Component({
selector: 'subscriptionTest',
template: `...`,
})
export class SubTestComponent {
first;
second;
third;
constructor(private remote: RemoteService){}
ngOnInit() {
this.first = remote.getSomeData().subscribe(data => // do something);
this.second = Observable.interval(500).subscribe(event => // do something);
this.third = remote.getSomeOtherData().subscribe(data => // do something);
}
ngOnDestroy() {
this.first.unsubscribe();
this.second.unsubscribe();
this.third.unsubscribe();
}
}
Antwort #1
Wenn Sie sich nicht wiederholen wollen, verwenden Sie eine Superklasse:
/**
* Unsubscribe from any Observable using takeUntil and this.destroy$
* someObservable.pipe( // lettable operators in rxjs ^5.5.0
* ...
* takeUntil(destroy$)
* )
* .subscribe(....
**/
export class Destroyer implements OnDestroy {
destroy$: Subject<boolean> = new Subject<boolean>();
ngOnDestroy() {
// Unsubscribe from whatever used takeUntil(destroy$)
this.destroy$.next(true);
// Now let's also unsubscribe from the subject itself:
this.destroy$.unsubscribe();
}
}
Verwende das überall:
export class SomeComponent extends Destroyer{
constructor(private remote: RemoteService){
super();
}
ngOnInit() {
remote.getSomeData()
.pipe(takeUntil(this.destroy$))
//.takeUntil(this.destroy$) // before rxjs ^5.5.0
.subscribe(data => {/* do something*/});
Observable.interval(500)
.pipe(takeUntil(this.destroy$))
//.takeUntil(this.destroy$) // before rxjs ^5.5.0
.subscribe(data => {/* do something*/});
}
}
// optional. You don't need ngOnDestroy everywhere.
ngOnDestroy(): void {
// Let Destroyer trigger unsubscribe
super.ngOnDestroy();
// ...SomeComponent other cleanup.
}
}
Antwort #2
Der takeUntil-Operator ist eine einfache Möglichkeit, sich „automatisch“ von jeder Subscription abzumelden, Beispiel :
@Component({...})
export class AppComponent implements OnInit, OnDestroy {
destroy$: Subject<boolean> = new Subject<boolean>();
constructor(private apollo: Apollo) {
}
ngOnInit() {
this.apollo.watchQuery({
query: gql`
query getAllPosts {
allPosts {
title
description
publishedAt
}
}
`
})
.takeUntil(this.destroy$)
.subscribe(({data}) => {
console.log(data);
});
remote.getSomeData().subscribe(data => // do something);
Observable.interval(500).subscribe(event => // do something);
remote.getSomeOtherData().subscribe(data => // do something);
}
onStartInterval() {
Observable
.interval(250)
.takeUntil(this.destroy$)
.subscribe(val => {
console.log('Current value:', val);
});
}
ngOnDestroy() {
this.destroy$.next(true);
// Now let's also unsubscribe from the subject itself:
this.destroy$.unsubscribe();
}
}
Du musst nicht jedes Abonnement deklarieren, sondern nur den .takeUntil(this.destroy$)-Operator bei jedem von ihnen hinzufügen
Quelle: https://alligator.io/angular/takeuntil-rxjs-unsubscribe/
Ein erstaunlicher Beitrag über Abonnements: Angular/RxJs Wann sollte ich von `Subscription` kündigen
