In einer Winkelanwendung haben wir ngOnDestroy()
Lifecycle Hook für eine Komponente/Direktive, und wir verwenden diesen Hook, um die Observables abzubestellen.
Ich möchte/beobachtbare Beobachtungen löschen, die in einem @injectable()
-Dienst erstellt wurden ..__ Ich habe einige Beiträge gesehen, die besagen, dass ngOnDestroy()
auch in einem Dienst verwendet werden kann.
Aber ist es eine gute Praxis und nur eine Möglichkeit, dies zu tun? Wann wird es gerufen? Jemand bitte klären.
OnDestroy Lifecycle-Hook ist in Anbietern verfügbar.
Lebenszyklus-Hook, der aufgerufen wird, wenn eine Anweisung, eine Pipe oder ein Dienst zerstört wird.
Hier ist ein Beispiel :
@Injectable()
class Service implements OnDestroy {
ngOnDestroy() {
console.log('Service destroy')
}
}
@Component({
selector: 'foo',
template: `foo`,
providers: [Service]
})
export class Foo {
constructor(service: Service) {}
ngOnDestroy() {
console.log('foo destroy')
}
}
@Component({
selector: 'my-app',
template: `<foo *ngIf="isFoo"></foo>`,
})
export class App {
isFoo = true;
constructor() {
setTimeout(() => {
this.isFoo = false;
}, 1000)
}
}
Beachten Sie, dass Service
im obigen Code eine Instanz ist, die zur Foo
-Komponente gehört. Sie kann also zerstört werden, wenn Foo
zerstört wird.
Für Anbieter, die zum Root-Injektor gehören, geschieht dies bei der Zerstörung der Anwendung. Dies ist hilfreich, um Speicherverluste bei mehreren Bootstraps zu vermeiden, d. H. Bei Tests.
Wenn ein Anbieter von einem übergeordneten Injektor in einer untergeordneten Komponente abonniert wird, wird er bei der Zerstörung der Komponente nicht zerstört. Dies liegt in der Verantwortung der Komponente, sich in der Komponente ngOnDestroy
abzumelden (wie in einer anderen Antwort erläutert).
Erstellen Sie eine Variable in Ihrem Dienst
subscriptions: Subscriptions[]=[];
Drücken Sie jedes Ihrer Abonnements als
this.subscriptions.Push(...)
Schreiben Sie eine dispose()
-Methode
dispose(){
this.subscriptions.forEach(subscription =>subscription.unsubscribe())
Rufen Sie diese Methode von ngOnDestroy aus Ihrer Komponente auf
ngOnDestroy(){
this.service.dispose();
}
Nur um zu klären - Sie brauchen nicht Observables
zu zerstören, sondern nur die Abonnements, die sie gemacht haben.
Es scheint, als hätten andere darauf hingewiesen, dass Sie ngOnDestroy
jetzt auch mit Services verwenden können. Link: https://angular.io/api/core/OnDestroy
Um meine Anwendung so modular wie möglich zu gestalten, verwende ich häufig Provider-Token, um einer Komponente einen Dienst bereitzustellen. Es scheint, dass diese NICHT ihre ngOnDestroy
-Methoden erhalten, die aufgerufen werden :-(
z.B.
export const PAYMENTPANEL_SERVICE = new InjectionToken<PaymentPanelService>('PAYMENTPANEL_SERVICE');
Mit einem Provider-Abschnitt in einer Komponente:
{
provide: PAYMENTPANEL_SERVICE,
useExisting: ShopPaymentPanelService
}
Bei meiner ShopPaymentPanelService
wird die ngOnDestroy
-Methode NICHT aufgerufen, wenn die Komponente entsorgt wird. Ich habe das gerade auf die harte Tour herausgefunden!
Eine Problemumgehung besteht darin, den Dienst in Verbindung mit useExisting
bereitzustellen.
[
ShopPaymentPanelService,
{
provide: PAYMENTPANEL_SERVICE,
useExisting: ShopPaymentPanelService
}
]
Als ich dies tat, wurde das ngOnDispose
wie erwartet aufgerufen.
Nicht sicher, ob dies ein Fehler ist oder nicht, aber sehr unerwartet.
Ich bevorzuge dieses takeUntil(onDestroy$)
-Muster, das von Pipe-Operatoren aktiviert wird. Ich finde es gut, dass dieses Muster prägnanter und sauberer ist und klar die Absicht vermittelt, ein Abonnement bei Ausführung des OnDestroy
Lebenszyklus-Hooks zu beenden.
Dieses Muster funktioniert sowohl für Dienste als auch für Komponenten, die injizierte Observables abonnieren. Der unten stehende Skeleton-Code sollte genügend Details enthalten, um das Muster in Ihren eigenen Service zu integrieren. Stellen Sie sich vor, Sie importieren einen Dienst namens InjectedService
...
import { InjectedService } from 'where/it/lives';
import { Injectable, OnDestroy } from '@angular/core';
import { Observable } from 'rxjs/Rx';
import { takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class MyService implements OnDestroy {
private onDestroy$ = new Subject<boolean>();
constructor(
private injectedService: InjectedService
) {
// Subscribe to service, and automatically unsubscribe upon `ngOnDestroy`
this.injectedService.observableThing().pipe(
takeUntil(this.onDestroy$)
).subscribe(latestTask => {
if (latestTask) {
this.initializeDraftAllocations();
}
});
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
Das Thema Wann/Wie kann ich den Newsletter abbestellen, wird hier ausführlich behandelt: Angular/RxJs Wann sollte ich das Abo abbestellen