Müssen Sie sich von Angular 2 http-Aufrufen abmelden, um Speicherverluste zu vermeiden?
fetchFilm(index) {
var sub = this._http.get(`http://example.com`)
.map(result => result.json())
.map(json => {
dispatch(this.receiveFilm(json));
})
.subscribe(e=>sub.unsubscribe());
...
angular
memory-leaks
rxjs
angular2-http
born2net
quelle
quelle
Antworten:
Die Antwort lautet also nein, das tust du nicht.
Ng2
wird es selbst aufräumen.Die HTTP-Dienstquelle aus Angulars HTTP-XHR-Backend-Quelle:
Beachten Sie, wie es ausgeführt wird,
complete()
nachdem Sie das Ergebnis erhalten haben. Dies bedeutet, dass es sich nach Abschluss tatsächlich abmeldet. Sie müssen es also nicht selbst tun.Hier ist ein Test zur Validierung:
Wie erwartet können Sie sehen, dass es immer automatisch abgemeldet wird, nachdem Sie das Ergebnis erhalten und mit den beobachtbaren Operatoren fertig sind. Dies geschieht bei einer Zeitüberschreitung (Nr. 3), damit wir den Status des Observablen überprüfen können, wenn alles erledigt und abgeschlossen ist.
Und das Ergebnis
Es würde also kein Leck existieren, wenn Sie sich
Ng2
automatisch abmelden!Nizza zu erwähnen: Dies
Observable
wird kategorisiert, dafinite
im Gegensatz zu dem,infinite
Observable
was ein unendlicher Datenstrom ist, wieclick
zum Beispiel DOM- Listener ausgegeben werden kann .DANKE, @rubyboy für Hilfe dazu.
quelle
Worüber redet ihr Leute !!!
OK, es gibt zwei Gründe, sich von einem beobachtbaren Objekt abzumelden. Niemand scheint viel über den sehr wichtigen zweiten Grund zu sprechen!
(Bei HTTP wird dadurch auch die Anforderung im Browser abgebrochen, sodass keine Zeit mit dem Lesen der Antwort verschwendet wird. Dies ist jedoch eine Ausnahme von meinem Hauptpunkt unten.)
Die Relevanz von Nummer 2 hängt davon ab, was Ihr Abonnement-Handler tut:
Betrachten Sie einige Fälle:
1) Ein Anmeldeformular. Sie geben Benutzername und Passwort ein und klicken auf "Anmelden". Was passiert, wenn der Server langsam ist und Sie sich entscheiden, Escape zu drücken, um den Dialog zu schließen? Sie werden wahrscheinlich annehmen, dass Sie nicht angemeldet waren, aber wenn die http-Anforderung nach dem Drücken von Escape zurückgegeben wurde, führen Sie trotzdem die dort vorhandene Logik aus. Dies kann dazu führen, dass eine Weiterleitung zu einer Kontoseite, ein unerwünschtes Anmeldecookie oder eine Tokenvariable festgelegt wird. Dies ist wahrscheinlich nicht das, was Ihr Benutzer erwartet hat.
2) Ein Formular zum Senden einer E-Mail.
Wenn der
subscribe
Handler für "sendEmail" beispielsweise eine Animation "Ihre E-Mail wird gesendet" auslöst, Sie auf eine andere Seite weiterleitet oder versucht, auf alles zuzugreifen, was entsorgt wurde, können Ausnahmen oder unerwünschtes Verhalten auftreten.Achten Sie auch darauf, nicht anzunehmen,
unsubscribe()
dass "Abbrechen" bedeutet. Sobald die HTTP-Nachricht im Flug ist,unsubscribe()
wird die HTTP-Anforderung NICHT abgebrochen, wenn sie bereits Ihren Server erreicht hat. Die Antwort, die Sie erhalten, wird nur abgebrochen. Und die E-Mail wird wahrscheinlich gesendet.Wenn Sie das Abonnement erstellen, um die E-Mail direkt in einer UI-Komponente zu senden, möchten Sie sich wahrscheinlich bei der Entsorgung abmelden. Wenn die E-Mail jedoch von einem nicht UI-zentralisierten Dienst gesendet wird, müssen Sie dies wahrscheinlich nicht tun.
3) Eine Winkelkomponente, die zerstört / geschlossen wird. Alle http-Observables, die zu diesem Zeitpunkt noch ausgeführt werden, werden vervollständigt und ihre Logik ausgeführt, sofern Sie sich nicht abmelden
onDestroy()
. Ob die Konsequenzen trivial sind oder nicht, hängt davon ab, was Sie im Abonnement-Handler tun. Wenn Sie versuchen, etwas zu aktualisieren, das nicht mehr existiert, wird möglicherweise eine Fehlermeldung angezeigt.Manchmal haben Sie möglicherweise einige Aktionen, die Sie möchten, wenn die Komponente entsorgt wird, und einige, die Sie nicht möchten. Zum Beispiel haben Sie vielleicht einen Swoosh-Sound für eine gesendete E-Mail. Sie möchten wahrscheinlich, dass dies auch dann abgespielt wird, wenn die Komponente geschlossen wurde. Wenn Sie jedoch versuchen, eine Animation für die Komponente auszuführen, schlägt dies fehl. In diesem Fall wäre eine zusätzliche bedingte Logik innerhalb von subscribe die Lösung - und Sie möchten das beobachtbare http NICHT abbestellen.
Als Antwort auf die eigentliche Frage müssen Sie dies nicht tun, um Speicherlecks zu vermeiden. Sie müssen dies jedoch (häufig) tun, um zu vermeiden, dass unerwünschte Nebenwirkungen durch das Ausführen von Code ausgelöst werden, der Ausnahmen auslösen oder Ihren Anwendungsstatus beschädigen kann.
Tipp: Die
Subscription
enthält eineclosed
boolesche Eigenschaft, die in fortgeschrittenen Fällen hilfreich sein kann. Für HTTP wird dies festgelegt, wenn es abgeschlossen ist. In Angular kann es in einigen Situationen hilfreich sein, eine_isDestroyed
Eigenschaft festzulegen, inngDestroy
der Ihrsubscribe
Handler sie überprüfen kann .Tipp 2: Wenn Sie mehrere Abonnements bearbeiten, können Sie ein Ad-hoc-
new Subscription()
Objekt undadd(...)
alle anderen Abonnements erstellen. Wenn Sie sich also vom Hauptobjekt abmelden, werden auch alle hinzugefügten Abonnements abgemeldet.quelle
Das Aufrufen der
unsubscribe
Methode dient eher dazu, eine laufende HTTP-Anforderung abzubrechen, da diese Methode dieabort
für das zugrunde liegende XHR-Objekt aufruft und Listener für die Lade- und Fehlerereignisse entfernt:Das heißt,
unsubscribe
entfernt Zuhörer ... Es könnte also eine gute Idee sein, aber ich denke nicht, dass es für eine einzelne Anfrage notwendig ist ;-)Hoffe es hilft dir, Thierry
quelle
y = x.subscribe((x)=>data = x);
Dann änderte ein Benutzer die Eingaben undx.subscribe((x)=>cachlist[n] = x); y.unsubscribe()
hey, Sie haben unsere Serverressourcen verwendet, ich habe gewonnen Wirf dich nicht weg ..... und in einem anderen Szenario: ruf einfachy.stop()
alles wegwerfenDas Abbestellen ist ein MUSS, wenn Sie ein deterministisches Verhalten für alle Netzwerkgeschwindigkeiten wünschen .
Stellen Sie sich vor , Komponente A wird in einer Registerkarte gerendert. Klicken Sie auf eine Schaltfläche, um eine GET-Anfrage zu senden. Es dauert 200 ms, bis die Antwort zurückkommt. Sie können die Registerkarte also jederzeit schließen, wenn Sie wissen, dass der Computer schneller als Sie ist und die http-Antwort verarbeitet und abgeschlossen ist, bevor die Registerkarte geschlossen und Komponente A zerstört wird.
Wie wäre es mit einem sehr langsamen Netzwerk? Wenn Sie auf eine Schaltfläche klicken, dauert es 10 Sekunden, bis die 'GET'-Anforderung ihre Antwort erhält. Nach 5 Sekunden Wartezeit entscheiden Sie sich jedoch, die Registerkarte zu schließen. Dadurch wird die Komponente A zerstört, die zu einem späteren Zeitpunkt gesammelt werden soll. Warte eine Minute! , wir haben uns nicht abgemeldet - jetzt, 5 Sekunden später, kommt eine Antwort zurück und die Logik in der zerstörten Komponente wird ausgeführt. Diese Ausführung wird jetzt in Betracht gezogen
out-of-context
und kann zu vielen Dingen führen, einschließlich einer sehr geringen Leistung.Daher
takeUntil()
empfiehlt es sich, http-Aufrufe zu verwenden und abzubestellen, wenn die Komponente zerstört wird.quelle
BehaviorSubject()
statt und rufen Sie einfachcomplete()
inngOnDestroy()
?BehaviourSubject
das anders sein?Auch beim neuen HttpClient-Modul bleibt das gleiche Verhalten erhalten
quelle
Sie sollten sich nicht von Observables abmelden, die automatisch abgeschlossen werden (z. B. HTTP, Aufrufe). Aber es ist notwendig, sich von unendlichen Observablen wie abzumelden
Observable.timer()
.quelle
Lesen Sie nach einer Weile des Testens die Dokumentation und den Quellcode des HttpClient.
HttpClient:
https://github.com/angular/angular/blob/master/packages/common/http/src/client.tsHttpXhrBackend :
https://github.com/angular/angular/blob/master/packages/common/http/src/xhr.tsHttpClientModule
: https://indepth.dev/exploring-the-httpclientmodule-in-angular/Angular Univeristy: https://blog.angular-university.io/angular-http/
Und die Antwort auf die gesamte Ausgabe von "MUSS ich" abbestellen?
Es hängt davon ab, ob. HTTP-Aufruf Memoryleaks sind kein Problem. Die Probleme sind die Logik in Ihren Rückruffunktionen.
Zum Beispiel: Routing oder Login.
Wenn es sich bei Ihrem Anruf um einen Anmeldeanruf handelt, müssen Sie sich nicht abmelden. Sie müssen jedoch sicherstellen, dass Sie die Antwort in Abwesenheit des Benutzers ordnungsgemäß verarbeiten, wenn der Benutzer die Seite verlässt.
Von nervig bis gefährlich
Stellen Sie sich vor, das Netzwerk ist langsamer als gewöhnlich, der Anruf dauert länger als 5 Sekunden, und der Benutzer verlässt die Anmeldeansicht und wechselt zu einer "Support-Ansicht".
Die Komponente ist möglicherweise nicht aktiv, aber das Abonnement. Im Falle einer Antwort wird der Benutzer plötzlich umgeleitet (abhängig von Ihrer Implementierung von handleResponse ()).
Das ist nicht gut
Stellen Sie sich auch vor, der Benutzer verlässt den PC und glaubt, noch nicht angemeldet zu sein. Aber Ihre Logik meldet den Benutzer an, jetzt haben Sie ein Sicherheitsproblem.
Was können Sie tun, ohne sich abzumelden?
Machen Sie Ihren Anruf abhängig vom aktuellen Status der Ansicht:
Benutzer
.pipe(takeWhile(value => this.isActive))
, um sicherzustellen, dass die Antwort nur verarbeitet wird, wenn die Ansicht aktiv ist.Aber wie können Sie sicher sein, dass das Abonnement keine Speicherlecks verursacht?
Sie können protokollieren, wenn "teardownLogic" angewendet wird.
Die TeardownLogic eines Abonnements wird aufgerufen, wenn das Abonnement leer oder nicht abonniert ist.
Sie müssen sich nicht abmelden. Sie sollten wissen, ob es Probleme in Ihrer Logik gibt, die Probleme in Ihrem Abonnement verursachen können. Und pass auf sie auf. In den meisten Fällen ist dies kein Problem. Insbesondere bei kritischen Aufgaben wie der Autorisierung sollten Sie sich jedoch um unerwartetes Verhalten kümmern, sei es mit "Abbestellen" oder einer anderen Logik wie Piping- oder bedingten Rückruffunktionen.
warum nicht einfach immer abbestellen?
Stellen Sie sich vor, Sie stellen eine Put- oder Post-Anfrage. Der Server empfängt die Nachricht so oder so, nur die Antwort dauert eine Weile. Wenn Sie sich abmelden, wird der Beitrag nicht rückgängig gemacht oder abgelegt. Wenn Sie sich jedoch abmelden, haben Sie nicht die Möglichkeit, die Antwort zu bearbeiten oder den Benutzer zu informieren, z. B. über einen Dialog oder einen Toast / eine Nachricht usw.
Dies lässt den Benutzer glauben, dass die Put / Post-Anfrage nicht ausgeführt wurde.
Es kommt also darauf an. Es ist Ihre Entwurfsentscheidung, wie Sie mit solchen Problemen umgehen.
quelle
Sie sollten diesen Artikel unbedingt lesen . Es zeigt Ihnen, warum Sie sich auch von http immer abmelden sollten .
Aktualisieren
Die obige Bestätigung scheint wahr zu sein, aber wenn die Antwort zurückkommt, wird das http-Abonnement trotzdem zerstört
quelle
RxJS Observable sind grundsätzlich zugeordnet und funktionieren entsprechend, wenn Sie es abonnieren. Wenn wir das Observable erstellen und die Bewegung, die wir vervollständigen, wird Observable automatisch geschlossen und abgemeldet.
Sie arbeiten auf die gleiche Weise wie die Beobachter, aber in einer ganz anderen Reihenfolge. Die bessere Vorgehensweise, um sie abzubestellen, wenn eine Komponente zerstört wird. Wir könnten dies anschließend tun, indem wir z. this. $ manageSubscription.unsubscibe ()
Wenn wir die beobachtbare Syntax wie unten erwähnt erstellt haben, wie z
** return new Observable ((Beobachter) => {** // Es macht beobachtbar im kalten Zustand ** Observer.complete () **}) **
quelle