Wann sollte ich die Subscription
Instanzen speichern und unsubscribe()
während des NgOnDestroy-Lebenszyklus aufrufen und wann kann ich sie einfach ignorieren?
Das Speichern aller Abonnements führt zu viel Chaos im Komponentencode.
HTTP-Client-Handbuch ignoriert Abonnements wie folgt:
getHeroes() {
this.heroService.getHeroes()
.subscribe(
heroes => this.heroes = heroes,
error => this.errorMessage = <any>error);
}
In der gleichen Zeit sagt Route & Navigation Guide , dass:
Irgendwann werden wir woanders navigieren. Der Router entfernt diese Komponente aus dem DOM und zerstört sie. Wir müssen nach uns selbst aufräumen, bevor das passiert. Insbesondere müssen wir uns abmelden, bevor Angular die Komponente zerstört. Andernfalls kann es zu einem Speicherverlust kommen.
Wir melden uns von unserer
Observable
in derngOnDestroy
Methode ab.
private sub: any;
ngOnInit() {
this.sub = this.route.params.subscribe(params => {
let id = +params['id']; // (+) converts string 'id' to a number
this.service.getHero(id).then(hero => this.hero = hero);
});
}
ngOnDestroy() {
this.sub.unsubscribe();
}
angular
rxjs
observable
subscription
angular-component-life-cycle
Sergey Tihon
quelle
quelle
Subscription
s tohttp-requests
kann ignoriert werden, da sie nuronNext
einmal anrufen und dann anrufenonComplete
. DerRouter
ruft stattdessenonNext
wiederholt an und ruft möglicherweise nie anonComplete
(nicht sicher ...). Gleiches gilt fürObservable
s vonEvent
s. Also ich denke das sollte seinunsubscribed
.subscribe
selbst, der potenziell Ressourcen vorgelagert zuweist.Antworten:
--- Bearbeiten 4 - Zusätzliche Ressourcen (2018/09/01)
In einer kürzlich erschienenen Folge von Adventures in Angular diskutieren Ben Lesh und Ward Bell die Fragen, wie / wann eine Komponente abgemeldet werden muss. Die Diskussion beginnt gegen 1:05:30 Uhr.
Ward erwähnt
right now there's an awful takeUntil dance that takes a lot of machinery
und Shai Reznik erwähntAngular handles some of the subscriptions like http and routing
.Als Antwort darauf erwähnt Ben, dass es derzeit Diskussionen gibt, die es Observables ermöglichen, sich in die Lebenszyklusereignisse der Angular-Komponente einzubinden, und Ward schlägt eine Observable von Lebenszyklusereignissen vor, die eine Komponente abonnieren könnte, um zu wissen, wann Observables abgeschlossen werden müssen, die als interner Status der Komponente verwaltet werden.
Das heißt, wir brauchen jetzt meistens Lösungen. Hier sind einige andere Ressourcen.
Eine Empfehlung für das
takeUntil()
Muster von RxJs Kernteammitglied Nicholas Jamieson und eine tslint-Regel, um es durchzusetzen. https://ncjamieson.com/avoiding-takeuntil-leaks/Leichtes npm-Paket, das einen Observable-Operator verfügbar macht, der eine Komponenteninstanz (
this
) als Parameter verwendet und sich währenddessen automatisch abmeldetngOnDestroy
. https://github.com/NetanelBasal/ngx-take-until-destroyEine weitere Variante des oben genannten mit etwas besserer Ergonomie, wenn Sie keine AOT-Builds ausführen (aber wir sollten jetzt alle AOT ausführen). https://github.com/smnbbrv/ngx-rx-collector
Benutzerdefinierte Direktive
*ngSubscribe
, die wie eine asynchrone Pipe funktioniert, jedoch eine eingebettete Ansicht in Ihrer Vorlage erstellt, sodass Sie in Ihrer Vorlage auf den Wert "Unwrapped" verweisen können. https://netbasal.com/diy-subscription-handling-directive-in-angular-c8f6e762697fIn einem Kommentar zu Nicholas 'Blog erwähne ich, dass eine Überbeanspruchung
takeUntil()
ein Zeichen dafür sein könnte, dass Ihre Komponente versucht, zu viel zu tun, und dass die Trennung Ihrer vorhandenen Komponenten in Feature- und Präsentationskomponenten in Betracht gezogen werden sollte. Sie können dann| async
das Observable von der Feature-Komponente in eineInput
der Presentational-Komponenten umwandeln, was bedeutet, dass nirgendwo Abonnements erforderlich sind. Lesen Sie mehr über diesen Ansatz hier--- Edit 3 - Die 'offizielle' Lösung (2017/04/09)
Ich habe mit Ward Bell über diese Frage bei NGConf gesprochen (ich habe ihm sogar diese Antwort gezeigt, die er für richtig hielt), aber er hat mir gesagt, dass das Docs-Team für Angular eine Lösung für diese Frage hat, die nicht veröffentlicht wurde (obwohl sie daran arbeiten, sie zu genehmigen ). Er sagte mir auch, ich könnte meine SO-Antwort mit der bevorstehenden offiziellen Empfehlung aktualisieren.
Die Lösung, die wir alle in Zukunft verwenden sollten, besteht darin
private ngUnsubscribe = new Subject();
, allen Komponenten ein Feld hinzuzufügen, deren Klassencode s.subscribe()
aufruftObservable
.Wir rufen dann
this.ngUnsubscribe.next(); this.ngUnsubscribe.complete();
unserengOnDestroy()
Methoden auf.Die geheime Sauce (wie bereits von @metamaker erwähnt ) besteht darin,
takeUntil(this.ngUnsubscribe)
vor jedem unserer.subscribe()
Anrufe anzurufen, um sicherzustellen , dass alle Abonnements bereinigt werden, wenn die Komponente zerstört wird.Beispiel:
Hinweis: Es ist wichtig, den
takeUntil
Bediener als letzten hinzuzufügen , um Undichtigkeiten mit dazwischen liegenden Observablen in der Bedienerkette zu vermeiden.--- Bearbeiten 2 (28.12.2016)
Quelle 5
Im Angular-Lernprogramm im Kapitel "Routing" heißt es nun: "Der Router verwaltet die von ihm bereitgestellten Observables und lokalisiert die Abonnements. Die Abonnements werden bereinigt, wenn die Komponente zerstört wird, und schützen so vor Speicherlecks, sodass wir uns nicht abmelden müssen." die Routenparameter beobachtbar. " - Mark Rajcok
Hier ist eine Diskussion über die Github-Probleme in den Angular-Dokumenten zu Router Observables, in denen Ward Bell erwähnt, dass eine Klärung all dessen in Arbeit ist.
--- Bearbeiten 1
Quelle 4
In diesem Video von NgEurope sagt Rob Wormald auch, dass Sie Router Observables nicht abbestellen müssen. Er erwähnt auch den
http
Service undActivatedRoute.params
in diesem Video vom November 2016 .--- Ursprüngliche Antwort
TLDR:
Für diese Frage gibt es (2) Arten von
Observables
- endlichem Wert und unendlichem Wert.http
Observables
erzeugen endliche (1) Werte und so etwas wie ein DOMevent listener
Observables
erzeugen unendliche Werte.Wenn Sie manuell aufrufen
subscribe
(ohne asynchrone Pipe), dannunsubscribe
von unendlichObservables
.Mach dir keine Sorgen um endliche ,
RxJs
werde dich um sie kümmern.Quelle 1
Ich habe hier eine Antwort von Rob Wormald in Angulars Gitter gefunden .
Er sagt (ich habe mich aus Gründen der Klarheit neu organisiert und die Betonung liegt bei mir)
Außerdem erwähnt er in diesem Youtube-Video zu Observables, dass
they clean up after themselves
... im Zusammenhang mit Observables, diecomplete
(wie Promises, die immer vollständig sind, weil sie immer einen Wert produzieren und enden) - wir haben uns nie Sorgen gemacht, Promises abzumelden, um sicherzustellen, dass sie dasxhr
Ereignis bereinigen Zuhörer, richtig?).Quelle 2
Auch in der Rangle-Anleitung zu Angular 2 heißt es
Wann gilt der Satz
our Observable has a longer lifespan than our subscription
?Dies gilt, wenn ein Abonnement in einer Komponente erstellt wird, die vor (oder nicht lange vor) dem
Observable
Abschluss zerstört wird.Ich habe dies als Bedeutung gelesen, wenn wir eine
http
Anfrage oder ein Observable abonnieren , das 10 Werte ausgibt und unsere Komponente zerstört wird, bevor diesehttp
Anfrage zurückkehrt oder die 10 Werte ausgegeben wurden, sind wir immer noch in Ordnung!Wenn die Anforderung zurückkehrt oder der 10. Wert endgültig ausgegeben
Observable
wird, ist der Vorgang abgeschlossen und alle Ressourcen werden bereinigt.Quelle 3
Wenn wir uns dieses Beispiel aus derselben Rangle-Anleitung ansehen, können wir sehen, dass für das
Subscription
to einroute.params
erforderlich ist,unsubscribe()
da wir nicht wissen, wann sich dieseparams
nicht mehr ändern (neue Werte ausgeben ).Die Komponente könnte durch Wegnavigation zerstört werden. In diesem Fall ändern sich die Routenparameter wahrscheinlich noch (sie können sich technisch bis zum Ende der App ändern), und die im Abonnement zugewiesenen Ressourcen werden weiterhin zugewiesen, da keine vorhanden ist
completion
.quelle
complete()
von selbst scheint die Abonnements nicht zu bereinigen. Ich glaube jedoch, dass das Aufrufennext()
und danncomplete()
das AufhörentakeUntil()
nur dann beendet wird, wenn ein Wert erzeugt wird, nicht wenn die Sequenz beendet ist.Subject
innerhalb einer Komponente und das Umschalten mit,ngIf
um auszulösenngOnInit
und zungOnDestroy
zeigen, dass der Betreff und seine Abonnements niemals abgeschlossen oder entsorgt werden (einfinally
Operator mit dem Abonnement verbunden). Ich nenne mussSubject.complete()
inngOnDestroy
, so dass die Zeichnungen nach sich aufzuräumen können.takeUnitl
wir den Ansatz verwenden, müssen wir uns nie manuell von Observablen abmelden? Ist das der Fall? Darüber hinaus warum brauchen wir Anrufnext()
in diengOnDestroy
, warum nicht einfach anrufencomplete()
?Sie müssen keine Abonnements haben und sich manuell abmelden. Verwenden Sie die Kombination aus Betreff und takeUntil , um Abonnements wie ein Chef zu behandeln:
Der alternative Ansatz , der von @acumartini in Kommentaren vorgeschlagen wurde , verwendet takeWhile anstelle von takeUntil . Sie mögen es vorziehen, aber denken Sie daran, dass auf diese Weise Ihre Observable-Ausführung bei ngDestroy Ihrer Komponente nicht abgebrochen wird (z. B. wenn Sie zeitaufwändige Berechnungen durchführen oder auf Daten vom Server warten). Die auf takeUntil basierende Methode hat diesen Nachteil nicht und führt zur sofortigen Stornierung der Anfrage. Vielen Dank an @AlexChe für die ausführliche Erklärung in den Kommentaren .
Also hier ist der Code:
quelle
takeUntil
undtakeWhile
. Ersteres wird von der beobachtbaren Quelle sofort nach dem Auslösen abgemeldet, während letzteres nur dann abgemeldet wird, wenn der nächste Wert von der beobachtbaren Quelle erzeugt wird. Wenn das Erzeugen eines Werts durch die beobachtbare Quelle eine ressourcenintensive Operation ist, kann die Auswahl zwischen beiden über die Stilpräferenz hinausgehen. Siehe das PlunktakeUntil
vstakeWhile
, jedoch nicht für unseren speziellen Fall. Wenn wir Listener für die Zerstörung von Komponenten abbestellen müssen, überprüfen wir nur den booleschen Wert wie() => alive
intakeWhile
, sodass keine zeit- / speicherintensiven Operationen verwendet werden und der Unterschied ziemlich stark vom Styling abhängt (ofc für diesen speziellen Fall).Observable
, die intern Kryptowährung abbaut und einnext
Ereignis für jede abgebaute Münze auslöst. Das Abbauen einer solchen Münze dauert einen Tag. Mit werdentakeUntil
wir unsObservable
sofort vom Source Mining abmelden, sobaldngOnDestroy
es während unserer Komponentenzerstörung aufgerufen wird. Somit kann die Mining-Observable
Funktion ihren Betrieb während dieses Vorgangs sofort abbrechen.takeWhile
, in derngOnDestory
wir die Boolesche Variable gerade eingestellt haben . Die Mining-Observable
Funktion funktioniert jedoch möglicherweise noch bis zu einem Tag. Erst dann wird beimnext
Aufrufen festgestellt, dass keine Abonnements aktiv sind und gekündigt werden müssen.Die Abonnementklasse hat eine interessante Funktion:
Sie können ein aggregiertes Abonnementobjekt erstellen, das alle Ihre Abonnements gruppiert. Sie tun dies, indem Sie ein leeres Abonnement erstellen und es mithilfe seiner
add()
Methode hinzufügen . Wenn Ihre Komponente zerstört wird, müssen Sie nur das Gesamtabonnement abbestellen.quelle
takeUntil
Ansatz im Vergleich zu diesem Ansatz zum Sammeln von Abonnements und Anrufen finden Sie unter medium.com/@benlesh/rxjs-dont-unsubscribe-6753ed4fda87unsubscribe
. (Dieser Ansatz scheint mir viel sauberer zu sein.)this.subscriptions
null istsub = subsciption.add(..).add(..)
da dies in vielen Fällen zu unerwarteten Ergebnissen führt. Github.com/ReactiveX/rxjs/issues/2769#issuecomment-345636477Einige der Best Practices für das Abbestellen von Observablen in Angular-Komponenten:
Ein Zitat aus
Routing & Navigation
Und bei der Beantwortung der folgenden Links:
http
BeobachtbarenIch habe einige der Best Practices für das Abbestellen von Observablen in Angular-Komponenten gesammelt, um sie mit Ihnen zu teilen:
http
Eine beobachtbare Abmeldung ist an Bedingungen geknüpft, und wir sollten die Auswirkungen des "Abonnement-Rückrufs" berücksichtigen, der ausgeführt wird, nachdem die Komponente von Fall zu Fall zerstört wurde. Wir wissen, dass der Winkel dashttp
Beobachtbare selbst abmeldet und reinigt (1) , (2) . Dies gilt zwar aus Sicht der Ressourcen, erzählt aber nur die halbe Geschichte. Nehmen wir an, wir sprechen über einen direkten Anrufhttp
aus einer Komponente heraus, und diehttp
Antwort dauerte länger als erforderlich, sodass der Benutzer die Komponente geschlossen hat. Dassubscribe()
Der Handler wird auch dann aufgerufen, wenn die Komponente geschlossen und zerstört wird. Dies kann unerwünschte Nebenwirkungen haben und in den schlimmsten Szenarien den Anwendungsstatus unterbrochen lassen. Es kann auch Ausnahmen verursachen, wenn der Code im Rückruf versucht, etwas aufzurufen, das gerade entsorgt wurde. Gleichzeitig sind sie jedoch gelegentlich erwünscht. Nehmen wir an, Sie erstellen einen E-Mail-Client und lösen einen Sound aus, wenn die E-Mail gesendet wurde. Nun, Sie möchten, dass dies auch dann geschieht, wenn die Komponente geschlossen ist ( 8 ).AsyncPipe
so viel wie möglich, da sich das bei der Zerstörung von Komponenten beobachtbare Element automatisch abmeldet.ActivatedRoute
Observablen ab, z. B.route.params
wenn sie in einer verschachtelten (in tpl mit dem Komponentenselektor hinzugefügt) oder dynamischen Komponente abonniert sind, da sie möglicherweise mehrmals abonniert werden, solange die übergeordnete / Host-Komponente vorhanden ist. Sie müssen sie in anderen Szenarien nicht abbestellen, wie im obigen Zitat aus denRouting & Navigation
Dokumenten erwähnt.Hinweis: In Bezug auf Dienste mit Gültigkeitsbereich, dh Komponentenanbieter, werden diese zerstört, wenn die Komponente zerstört wird. In diesem Fall sollten wir, wenn wir ein innerhalb dieses Anbieters beobachtbares Objekt abonnieren, in Betracht ziehen, es mit dem
OnDestroy
Lifecycle-Hook abzubestellen, der gemäß den Dokumenten aufgerufen wird, wenn der Dienst zerstört wird.takeUntil
(3) verwalten oder dieses unter (4) genanntenpm
Paket verwenden. Der einfachste Weg, sich von Observables in Angular abzumelden .FormGroup
Beobachten Sie immer Observables wieform.valueChanges
undform.statusChanges
Renderer2
Service wierenderer2.listen
HostListener
da Angular sich bei Bedarf gut um das Entfernen der Ereignis-Listener kümmert und potenzielle Speicherverluste aufgrund von Ereignisbindungen verhindert.Ein schöner letzter Tipp : Wenn Sie nicht wissen, ob ein Observable automatisch abgemeldet / abgeschlossen wird oder nicht, fügen Sie einen
complete
Rückruf hinzusubscribe(...)
und prüfen Sie, ob es aufgerufen wird, wenn die Komponente zerstört wird.quelle
ngOnDestroy
aufgerufen, wenn der Dienst auf einer anderen Ebene als der Stammebene bereitgestellt wird, z. B. explizit in einer Komponente, die später entfernt wird. In diesen Fällen sollten Sie sich von den inneren Observablen des Dienstes abmeldenngOnDestroy
wird immer aufgerufen, wenn Dienste zerstört werden. Github.com/angular/angular/commit/…Feel free to unsubscribe anyway. It is harmless and never a bad practice.
und in Bezug auf Ihre Frage kommt es darauf an. Wenn die untergeordnete Komponente mehrmals initiiert wird (z. B. innerhalb hinzugefügtngIf
oder dynamisch geladen wird), müssen Sie sich abmelden, um zu vermeiden, dass demselben Beobachter mehrere Abonnements hinzugefügt werden. Sonst keine Notwendigkeit. Ich bevorzuge es jedoch, die untergeordnete Komponente abzubestellen, da sie dadurch wiederverwendbarer und isolierter wird, wie sie verwendet werden könnte.Es hängt davon ab, ob. Wenn Sie durch Aufrufen
someObservable.subscribe()
eine Ressource halten, die manuell freigegeben werden muss, wenn der Lebenszyklus Ihrer Komponente abgelaufen ist, sollten Sie aufrufentheSubscription.unsubscribe()
, um Speicherverluste zu vermeiden.Schauen wir uns Ihre Beispiele genauer an:
getHero()
gibt das Ergebnis von zurückhttp.get()
. Wenn Sie sich den Quellcodehttp.get()
für Winkel 2 ansehen , werden zwei Ereignis-Listener erstellt:und indem Sie anrufen
unsubscribe()
, können Sie die Anfrage sowie die Zuhörer abbrechen:Beachten Sie, dass dies
_xhr
plattformspezifisch ist, aber ich denke, es ist sicher anzunehmen, dass es sich um eineXMLHttpRequest()
in Ihrem Fall handelt.Normalerweise ist dies ein ausreichender Beweis, um einen manuellen
unsubscribe()
Anruf zu rechtfertigen . Aber nach dieser WHATWG spec , dasXMLHttpRequest()
unterliegt die Garbage Collection , sobald es „fertig“ ist, auch wenn es Ereignis Zuhörer daran befestigt. Ich denke, das ist der Grund, warum Angular 2 Official Guide weglässtunsubscribe()
und GC die Hörer aufräumen lässt.Wie für Ihr zweites Beispiel hängt es von der Implementierung von ab
params
. Ab heute zeigt der eckige offizielle Leitfaden keine Abmeldung mehr vonparams
. Ich habe noch einmal in src nachgesehen und festgestellt, dass diesparams
nur ein BehaviorSubject ist . Da keine Ereignis-Listener oder Timer verwendet wurden und keine globalen Variablen erstellt wurden, sollte das Auslassen sicher seinunsubscribe()
.Die Quintessenz Ihrer Frage lautet: Rufen Sie immer
unsubscribe()
als Schutz vor Speicherverlusten auf, es sei denn, Sie sind sicher, dass bei der Ausführung des Observable keine globalen Variablen erstellt, keine Ereignis-Listener hinzugefügt, keine Timer festgelegt oder andere Aktionen ausgeführt werden, die zu Speicherverlusten führen .Wenn Sie Zweifel haben, prüfen Sie die Umsetzung dieses Observablen. Wenn das Observable eine Bereinigungslogik in sein Programm geschrieben hat
unsubscribe()
, die normalerweise vom Konstruktor zurückgegeben wird, haben Sie guten Grund, ernsthaft über einen Aufruf nachzudenkenunsubscribe()
.quelle
Die offizielle Dokumentation zu Angular 2 enthält eine Erklärung, wann Sie sich abmelden müssen und wann sie sicher ignoriert werden kann. Schauen Sie sich diesen Link an:
https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service
Suchen Sie nach dem Absatz mit der Überschrift Eltern und Kinder kommunizieren über einen Dienst und dann über das blaue Kästchen:
Ich hoffe das hilft dir.
quelle
Basierend auf: Verwenden der Klassenvererbung zum Verknüpfen mit dem Angular 2-Komponentenlebenszyklus
Ein weiterer generischer Ansatz:
Und benutze:
quelle
this.componentDestroyed$.next()
Anruf wie die von Sean oben akzeptierte Lösung ...Die offizielle Antwort von Edit # 3 (und Variationen) funktioniert gut, aber das, was mich dazu bringt, ist das "Durcheinander" der Geschäftslogik um das beobachtbare Abonnement.
Hier ist ein anderer Ansatz mit Wrappern.
Die Datei subscribeAndGuard.ts wird verwendet, um eine neue Observable-Erweiterung zum Umschließen
.subscribe()
und zum Umschließen zu erstellenngOnDestroy()
.Die Verwendung ist dieselbe wie
.subscribe()
mit Ausnahme eines zusätzlichen ersten Parameters, der auf die Komponente verweist.Hier ist eine Komponente mit zwei Abonnements, eines mit dem Wrapper und eines ohne. Die einzige Einschränkung ist, dass OnDestroy implementiert werden muss (falls gewünscht mit leerem Körper), andernfalls kann Angular die umschlossene Version nicht aufrufen.
Ein Demo-Plunker ist da
Ein zusätzlicher Hinweis: Re Edit 3 - Die 'offizielle' Lösung. Dies kann vereinfacht werden, indem takeWhile () anstelle von takeUntil () vor Abonnements verwendet wird und ein einfacher Boolescher Wert anstelle eines anderen Observable in ngOnDestroy verwendet wird.
quelle
Da die Lösung von seangwright (Edit 3) sehr nützlich zu sein scheint, empfand ich es auch als schwierig, diese Funktion in die Basiskomponente zu packen und anderen Projektteammitgliedern zu empfehlen, super () auf ngOnDestroy aufzurufen, um diese Funktion zu aktivieren.
Diese Antwort bietet eine Möglichkeit, sich von Superaufrufen zu befreien und "componentDestroyed $" zu einem Kern der Basiskomponente zu machen.
Und dann können Sie diese Funktion zum Beispiel frei nutzen:
quelle
Nach der Antwort von @seangwright habe ich eine abstrakte Klasse geschrieben, die die Abonnements von "unendlichen" Observablen in Komponenten behandelt:
Um es zu verwenden, erweitern Sie es einfach in Ihrer Winkelkomponente und rufen Sie die
subscribe()
Methode wie folgt auf:Es akzeptiert auch den Fehler und führt Rückrufe wie gewohnt, ein Beobachterobjekt oder gar keine Rückrufe durch. Denken
super.ngOnDestroy()
Sie daran, aufzurufen, wenn Sie diese Methode auch in der untergeordneten Komponente implementieren.Hier finden Sie eine zusätzliche Referenz von Ben Lesh: RxJS: Nicht abbestellen .
quelle
Ich habe die Lösung von Seangwright ausprobiert (Edit 3).
Dies funktioniert nicht für Observable, das durch Timer oder Intervall erstellt wurde.
Ich habe es jedoch mit einem anderen Ansatz zum Laufen gebracht:
quelle
Ich mag die letzten beiden Antworten, aber ich habe ein Problem , wenn die die Unterklasse verweist
"this"
inngOnDestroy
.Ich habe es so geändert, und es sieht so aus, als hätte es dieses Problem behoben.
quelle
this.ngOnDestroy = () => { f.bind(this)(); this.componentDestroyed$.complete(); };
Falls eine Abmeldung erforderlich ist, kann der folgende Operator für die beobachtbare Rohrleitungsmethode verwendet werden
es kann so verwendet werden:
Der Operator umschließt die ngOnDestroy-Methode der Komponente.
Wichtig: Der Bediener sollte der letzte in einem beobachtbaren Rohr sein.
quelle
Normalerweise müssen Sie sich abmelden, wenn die Komponenten zerstört werden, aber Angular wird dies im Laufe der Zeit immer mehr tun. In der neuen Nebenversion von Angular4 gibt es diesen Abschnitt zum Weiterleiten des Abmelden:
Das folgende Beispiel ist auch ein gutes Beispiel aus Angular, um eine Komponente zu erstellen und anschließend zu zerstören. Sehen Sie sich an, wie die Komponente OnDestroy implementiert. Wenn Sie onInit benötigen, können Sie sie auch in Ihrer Komponente implementieren, z. B. implementiert
OnInit, OnDestroy
quelle
Eine weitere kurze Ergänzung zu den oben genannten Situationen ist:
quelle
in der SPA-Anwendung bei ngOnDestroy- Funktion (Angular LifeCycle) Für jedes Abonnement müssen Sie sich abmelden . Vorteil => um zu verhindern, dass der Staat zu schwer wird.
Zum Beispiel: in Komponente1:
im Dienst:
in Komponente2:
quelle
Für die Bearbeitung des Abonnements verwende ich eine "Unsubscriber" -Klasse.
Hier ist die Unsubscriber-Klasse.
Und Sie können diese Klasse in jeder Komponente / jedem Service / Effekt usw. verwenden.
Beispiel:
quelle
Sie können die neueste
Subscription
Klasse verwenden, um das Observable mit nicht so unordentlichem Code abzubestellen.Wir können dies mit tun,
normal variable
aber es wirdoverride the last subscription
bei jedem neuen Abonnement so sein, also vermeiden Sie dies, und dieser Ansatz ist sehr nützlich, wenn Sie mit mehr Anzahl von Obseravables und Arten von Obeservables wieBehavoiurSubject
und arbeitenSubject
Abonnement
Sie können dies auf zwei Arten verwenden:
Sie können das Abonnement direkt an Subscription Array senden
mit
add()
vonSubscription
A
Subscription
kann untergeordnete Abonnements speichern und alle sicher abbestellen. Diese Methode behandelt mögliche Fehler (z. B. wenn untergeordnete Abonnements null sind).Hoffe das hilft.. :)
quelle
Das SubSink-Paket, eine einfache und konsistente Lösung zum Abbestellen
Wie noch niemand erwähnt hat, möchte ich das von Ward Bell erstellte Subsink-Paket empfehlen: https://github.com/wardbell/subsink#readme .
Ich habe es für ein Projekt verwendet, bei dem wir mehrere Entwickler sind, die es alle verwenden. Es hilft sehr, eine konsistente Arbeitsweise zu haben, die in jeder Situation funktioniert.
quelle
Für Observables, die direkt nach dem Ausgeben des Ergebnisses abgeschlossen werden, wie
AsyncSubject
oder zum Beispiel Observables von http-Anfragen und dergleichen, müssen Sie sich nicht abmelden. Es tut nicht weh, nach diesen zu rufenunsubscribe()
, aber wenn das Beobachtbareclosed
die Abmeldemethode ist, wird einfach nichts getan :Wenn Sie langlebige Observables haben, die im Laufe der Zeit mehrere Werte ausgeben (wie z. B. a
BehaviorSubject
oder aReplaySubject
), müssen Sie sich abmelden, um Speicherverluste zu vermeiden.Mit einem Pipe-Operator können Sie auf einfache Weise ein Observable erstellen, das direkt nach der Ausgabe eines Ergebnisses aus solch langlebigen Observables abgeschlossen wird. In einigen Antworten wird hier die
take(1)
Pfeife erwähnt. Aber ich bevorzuge diefirst()
Pfeife . Der Unterschied zutake(1)
ist, dass es:Ein weiterer Vorteil der ersten Pipe besteht darin, dass Sie ein Prädikat übergeben können, mit dessen Hilfe Sie den ersten Wert zurückgeben können, der bestimmte Kriterien erfüllt:
First wird direkt nach der Ausgabe des ersten Werts abgeschlossen (oder beim Übergeben eines Funktionsarguments den ersten Wert, der Ihrem Prädikat entspricht), sodass Sie sich nicht abmelden müssen.
Manchmal sind Sie sich nicht sicher, ob Sie eine langlebige Beobachtbarkeit haben oder nicht. Ich sage nicht, dass es eine gute Praxis ist, aber Sie könnten dann immer die hinzufügen
first
Pipe , um sicherzustellen, dass Sie sich nicht manuell abmelden müssen. Das Hinzufügen einer zusätzlichenfirst
Pipe zu einem Observable, das nur einen Wert ausgibt, schadet nicht.Während der Entwicklung können Sie das
single
Rohr verwenden , die fehlschlägt, wenn die beobachtbare Quelle mehrere Ereignisse ausgibt. Dies kann Ihnen helfen, die Art der beobachtbaren Daten zu untersuchen und festzustellen, ob eine Abmeldung erforderlich ist oder nicht.Die
first
undsingle
scheinen sehr ähnlich zu sein, beide Pipes können ein optionales Prädikat annehmen, aber die Unterschiede sind wichtig und werden in dieser Stackoverflow-Antwort hier gut zusammengefasst :Hinweis Ich habe versucht, in meiner Antwort mit Verweisen auf die offizielle Dokumentation so genau und vollständig wie möglich zu sein. Bitte kommentieren Sie, wenn etwas Wichtiges fehlt ...
quelle
--- Aktualisieren Sie Angular 9 und Rxjs 6 Solution
unsubscribe
imngDestroy
Lebenszyklus der WinkelkomponentetakeUntil
in RxjsngOnInit
, geschieht dies nur einmal, wenn die Komponente initialisiert wird.Wir haben auch
async
Pfeife. Diese wird jedoch für die Vorlage verwendet (nicht in der Winkelkomponente).quelle