Devez-vous vous désabonner des appels http Angular 2 pour éviter les fuites de mémoire?
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
la source
la source
Réponses:
Donc, la réponse est non, vous ne le faites pas.
Ng2
va le nettoyer lui-même.La source du service Http, à partir de la source backend Http XHR d'Angular:
Remarquez comment il s'exécute
complete()
après avoir obtenu le résultat. Cela signifie qu'il se désabonne à la fin. Vous n'avez donc pas besoin de le faire vous-même.Voici un test à valider:
Comme prévu, vous pouvez voir qu'il est toujours automatiquement désabonné après avoir obtenu le résultat et fini avec les opérateurs observables. Cela se produit sur un délai d'attente (# 3) afin que nous puissions vérifier l'état de l'observable une fois terminé et terminé.
Et le résultat
Ainsi, aucune fuite n'existerait lors de
Ng2
la désinscription automatique!Agréable à mentionner: ceci
Observable
est catégorisé carfinite
, contrairement à ceinfinite
Observable
qui est un flux infini de données peut être émis comme l'click
écouteur DOM par exemple.MERCI, @rubyboy pour votre aide à ce sujet.
la source
De quoi parlez-vous!!!
OK donc il y a deux raisons de se désinscrire de tout observable. Personne ne semble beaucoup parler de la deuxième raison très importante!
(Pour HTTP, cela annulera également la demande dans le navigateur - donc cela ne perdra pas de temps à lire la réponse. Mais c'est en fait un aparté à mon point principal ci-dessous.)
La pertinence du numéro 2 dépendra de ce que fait votre gestionnaire d'abonnement:
Prenons quelques cas:
1) Un formulaire de connexion. Vous entrez le nom d'utilisateur et le mot de passe et cliquez sur «Connexion». Que faire si le serveur est lent et que vous décidez d'appuyer sur Échap pour fermer la boîte de dialogue? Vous supposerez probablement que vous n'étiez pas connecté, mais si la demande http est retournée après avoir appuyé sur escape, alors vous exécuterez toujours la logique que vous avez là-bas. Cela peut entraîner une redirection vers une page de compte, un cookie de connexion indésirable ou une variable de jeton en cours de définition. Ce n'est probablement pas ce que votre utilisateur attendait.
2) Un formulaire «envoyer un e-mail».
Si le
subscribe
gestionnaire pour «sendEmail» fait quelque chose comme déclencher une animation «Votre e-mail est envoyé», vous transférer vers une autre page ou essayer d'accéder à tout ce qui a été supprimé, vous pouvez obtenir des exceptions ou un comportement indésirable.Faites également attention à ne pas supposer
unsubscribe()
«annuler». Une fois que le message HTTP est en vol,unsubscribe()
il n'annulera PAS la demande HTTP si elle a déjà atteint votre serveur. Cela n'annulera que la réponse qui vous reviendra. Et l'e-mail sera probablement envoyé.Si vous créez l'abonnement pour envoyer l'e-mail directement à l'intérieur d'un composant d'interface utilisateur, vous souhaiterez probablement vous désabonner lors de la suppression, mais si l'e-mail est envoyé par un service centralisé non-interface utilisateur, vous n'en aurez probablement pas besoin.
3) Un composant angulaire qui est détruit / fermé. Tous les observables http toujours en cours d'exécution à ce moment-là se termineront et exécuteront leur logique, sauf si vous vous désabonnez
onDestroy()
. Que les conséquences soient triviales ou non dépendra de ce que vous faites dans le gestionnaire d'abonnement. Si vous essayez de mettre à jour quelque chose qui n'existe plus, vous pouvez obtenir une erreur.Parfois, vous pouvez avoir certaines actions que vous souhaiteriez si le composant est supprimé, et d'autres non. Par exemple, vous avez peut-être un son «swoosh» pour un e-mail envoyé. Vous voudriez probablement que cela fonctionne même si le composant était fermé, mais si vous essayez d'exécuter une animation sur le composant, cela échouerait. Dans ce cas, une logique conditionnelle supplémentaire à l'intérieur de subscribe serait la solution - et vous ne voudriez PAS désinscrire le http observable.
Donc, en réponse à la question réelle, non, vous n'avez pas besoin de le faire pour éviter les fuites de mémoire. Mais vous devez le faire (souvent) pour éviter que des effets secondaires indésirables ne soient déclenchés par l'exécution de code qui peut lever des exceptions ou corrompre l'état de votre application.
Conseil: Le
Subscription
contient uneclosed
propriété booléenne qui peut être utile dans les cas avancés. Pour HTTP, cela sera défini à la fin. Dans Angular, il peut être utile dans certaines situations de définir une_isDestroyed
propriéténgDestroy
qui peut être vérifiée par votresubscribe
gestionnaire.Astuce 2: Si vous gérez plusieurs abonnements, vous pouvez créer un
new Subscription()
objet ad-hoc etadd(...)
tout autre abonnement - donc lorsque vous vous désabonnez de celui-ci, il désabonnera également tous les abonnements ajoutés.la source
L'appel de la
unsubscribe
méthode revient plutôt à annuler une requête HTTP en cours, car cette méthode appelleabort
celle sur l'objet XHR sous-jacent et supprime les écouteurs sur les événements de chargement et d'erreur:Cela dit,
unsubscribe
supprime les auditeurs ... Donc ça pourrait être une bonne idée mais je ne pense pas que ce soit nécessaire pour une seule demande ;-)J'espère que ça vous aide, Thierry
la source
y = x.subscribe((x)=>data = x);
alors un utilisateur change d'entrée etx.subscribe((x)=>cachlist[n] = x); y.unsubscribe()
bon vous avez utilisé nos ressources serveur, j'ai gagné ne vous jetez pas ..... et dans un autre scénario: appelez simplementy.stop()
tout jeterLa désinscription est un MUST si vous voulez un déterministe comportement à toutes les vitesses du réseau.
Imaginer que le composant A soit rendu dans un onglet - Vous cliquez sur un bouton pour envoyer une demande «GET». Il faut 200 ms pour que la réponse revienne. Ainsi, vous êtes sûr de fermer l'onglet à tout moment en sachant que la machine sera plus rapide que vous et la réponse http est traitée et terminée avant que l'onglet ne soit fermé et que le composant A soit détruit.
Que diriez-vous d'un réseau très lent? Vous cliquez sur un bouton, la demande «GET» prend 10 secondes pour recevoir sa réponse, mais après 5 secondes d'attente, vous décidez de fermer l'onglet. Cela détruira le composant A devant être récupéré ultérieurement. Attends une minute! , nous ne nous sommes pas désabonnés - maintenant 5 secondes plus tard, une réponse revient et la logique du composant détruit sera exécutée. Cette exécution est maintenant envisagée
out-of-context
et peut entraîner de nombreuses choses, notamment de très faibles performances.Ainsi, la meilleure pratique consiste à utiliser
takeUntil()
et à vous désabonner des appels http lorsque le composant est détruit.la source
BehaviorSubject()
place et il suffit d' appelercomplete()
enngOnDestroy()
?BehaviourSubject
il différent?Toujours avec le nouveau module HttpClient, reste le même comportement
la source
Vous ne devez pas vous désabonner des observables qui se terminent automatiquement (par exemple Http, appels). Mais il est nécessaire de se désabonner des observables infinis comme
Observable.timer()
.la source
Après un certain temps de test, lecture de la documentation et du code source du 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/Université angulaire: https://blog.angular-university.io/angular-http/
Et la réponse à toute la question de "ai-je besoin" de me désinscrire?
Ça dépend. Les fuites de mémoire des appels HTTP ne sont pas un problème. Les problèmes sont la logique de vos fonctions de rappel.
Par exemple: routage ou connexion.
Si votre appel est un appel de connexion, vous n'avez pas à vous "désinscrire" mais vous devez vous assurer que si l'utilisateur quitte la page, vous gérez la réponse correctement en l'absence de l'utilisateur.
D'ennuyeux à dangereux
Imaginez maintenant, le réseau est plus lent que d'habitude, l'appel prend plus de 5 secondes et l'utilisateur quitte la vue de connexion et passe à une "vue de support".
Le composant n'est peut-être pas actif mais l'abonnement. En cas de réponse, l'utilisateur sera soudainement redirigé (selon votre implémentation de handleResponse ()).
Ce n'est pas bon.
Imaginez également que l'utilisateur quitte le PC, croyant qu'il n'est pas encore connecté. Mais votre logique connecte l'utilisateur, vous avez maintenant un problème de sécurité.
Que pouvez-vous faire SANS vous désinscrire?
Rendre votre appel dépendant de l'état actuel de la vue:
L'utilisateur
.pipe(takeWhile(value => this.isActive))
doit s'assurer que la réponse n'est gérée que lorsque la vue est active.Mais comment être sûr que l'abonnement ne cause pas de fuites de mémoire?
Vous pouvez vous connecter si le "teardownLogic" est appliqué.
La déchirureLogic d'un abonnement sera appelée lorsque l'abonnement est vide ou non souscrit.
Vous n'êtes pas obligé de vous désinscrire. Vous devez savoir s'il y a des problèmes dans votre logique, qui pourraient causer des problèmes dans votre abonnement. Et prends soin d'eux. Dans la plupart des cas, ce ne sera pas un problème, mais surtout pour les tâches critiques telles que l'autorisation, vous devez faire attention aux comportements inattendus, que ce soit avec "unsubscribe" ou une autre logique comme la tuyauterie ou les fonctions de rappel conditionnel.
pourquoi ne pas simplement toujours vous désinscrire?
Imaginez que vous fassiez une demande de vente ou de publication. Le serveur reçoit le message de toute façon, la réponse prend un certain temps. Se désinscrire, n'annulera pas le message ni ne le mettra. Mais lorsque vous vous désabonnez, vous n'aurez pas la possibilité de gérer la réponse ou d'informer l'utilisateur, par exemple via une boîte de dialogue ou un toast / message, etc.
Ce qui fait croire à l'utilisateur que la demande put / post n'a pas été effectuée.
Cela dépend donc. C'est votre décision de conception, comment traiter ces problèmes.
la source
Vous devriez certainement lire cet article. Il vous montre pourquoi vous devez toujours vous désinscrire, même de http .
Mettre à jour
L'affirmation ci-dessus semble être vraie, mais de toute façon, quand la réponse revient, l'abonnement http est quand même détruit
la source
Les observables RxJS sont fondamentalement associés et fonctionnent en conséquence, vous vous y abonnez. Lorsque nous créons l'observable et le mouvement que nous le complétons, l'observable est automatiquement fermé et désabonné.
Ils travaillent de la même manière que les observateurs mais dans un ordre assez différent. La meilleure pratique pour les désinscrire lorsque le composant est en cours de destruction. Nous pourrions par la suite le faire par exemple. this. $ manageSubscription.unsubscibe ()
Si nous avons créé la syntaxe observable comme ci-dessous, telle que
** return new Observable ((observer) => {** // Il rend observable à froid ** observer.complete () **}) **
la source