Est-il nécessaire de se désabonner des observables créés par les méthodes Http?

avez-vous besoin de 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());
            ...
87
demandé sur Roy Ling 2016-01-27 19:33:50

6 réponses

donc la réponse est non, vous ne le faites pas. Ng2 nettoiera tout seul.

Le service Http de la source, à partir Angulaire Http XHR backend source:

enter image description here

remarquez comment fonctionne le complete() après avoir obtenu le résultat. Cela signifie qu'il se désabonne en fait à l'achèvement. Si vous n'avez pas besoin de le faire vous-même.

Voici un test pour valider:

  fetchFilms() {
    return (dispatch) => {
        dispatch(this.requestFilms());

        let observer = this._http.get(`${BASE_URL}`)
            .map(result => result.json())
            .map(json => {
                dispatch(this.receiveFilms(json.results));
                dispatch(this.receiveNumberOfFilms(json.count));
                console.log("2 isUnsubscribed",observer.isUnsubscribed);
                window.setTimeout(() => {
                  console.log("3 isUnsubscribed",observer.isUnsubscribed);
                },10);
            })
            .subscribe();
        console.log("1 isUnsubscribed",observer.isUnsubscribed);
    };
}

comme prévu, vous pouvez voir qu'il est toujours désabonné automatiquement après avoir obtenu le résultat et de finir avec les opérateurs observables. Cela se produit sur un timeout (#3) de sorte que nous pouvons vérifier l'état de l'observable lorsque tout est terminé et complété.

et le résultat

enter image description here

donc, aucune fuite n'existerait comme Ng2 auto désabonnement!

Nice to mention: Cette Observable est classé comme finite , contrairement à la infinite Observable qui est un infini de flux de données peuvent être émis comme DOM click port d'écoute par exemple.

merci, @rubyboy pour l'aide.

148
répondu born2net 2018-08-07 15:16:56

appeler la méthode unsubscribe revient plutôt à annuler une requête HTTP en cours puisque cette méthode appelle la abort sur l'objet XHR sous-jacent et supprime les écouteurs sur les événements de charge et d'erreur:

// From the XHRConnection class
return () => {
  _xhr.removeEventListener('load', onLoad);
  _xhr.removeEventListener('error', onError);
  _xhr.abort();
};

qui 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 requête; -)

J'espère que ça vous aidera, Thierry

17
répondu Thierry Templier 2016-01-27 16:42:58

de quoi parlez-vous?!!

OK donc il y a deux raisons fondamentales pour se désabonner de tout observable. Personne ne parle beaucoup de la seconde!

1) Nettoyer les ressources. Comme d'autres l'ont dit, il s'agit d'un problème négligeable pour les observables HTTP. Il va tout simplement de nettoyer lui-même.

2) empêcher le manipulateur subscribe d'être exécuté.

le l'importance du numéro 2 va dépendre de ce que fait votre gestionnaire:

si votre fonction de gestionnaire subscribe() a un effet secondaire indésirable lorsque le composant appelant est fermé, vous devez vous désabonner (ou ajouter une logique conditionnelle) pour l'empêcher d'être appelé.

Envisager un certain nombre de cas:

1) un formulaire de connexion. Vous entrez le nom d'utilisateur et le mot de passe et cliquez sur "Login". Que faire si le serveur est lent et vous décidez de cliquer sur Escape pour fermer le dialogue? Vous supposerez probablement que vous n'avez pas été connecté, mais si la requête http est revenue après que vous ayez frappé escape, alors vous exécuterez toujours la logique que vous avez là. Cela peut se traduire par une redirection, un cookie de connexion indésirable ou une variable token étant définie. Ce n'est probablement pas ce que votre utilisateur prévu.

2) un formulaire "envoyer un courriel". Une fois que le message HTTP est en vol, il est important de comprendre que unsubscribe() n'annulera pas la requête HTTP. Il est déjà sur son chemin - et ce n'est rien à voir avec Angular ou RxJS - c'est juste comment l'internet fonctionne. Il permettra d'accéder à votre serveur, et l'e-mail sera envoyé. (Vous devrez mettre en œuvre une sorte de mécanisme d'envoi différé comme le fait le bouton Annuler de Gmail si vous avez besoin d'un comportement plus sophistiqué.)

si le handler subscribe pour ' sendEmail' fait quelque chose comme déclencher une animation 'votre e-mail est envoyé', vous transférer à un autre route ou accès à un autre observable qui a été disposé alors vous obtiendrez des exceptions ou un comportement indésirable.

parfois, vous pouvez être quelque part entre des actions que vous voudriez et d'autres que vous ne voudriez pas. Par exemple, vous avez peut-être un son 'swoosh' pour un e-mail envoyé. Vous voudriez probablement que cela fonctionne même si le component était fermé, mais si vous essayez d'exécuter une animation sur le component qui est juste fermé, cela échouerait. Dans ce cas, une logique extra-conditionnelle inside subscribe serait la solution - et vous ne voudriez pas vous désabonner du http observable.

donc en réponse à la question actuelle, Non vous n'avez pas besoin de le faire pour éviter les fuites de mémoire. Mais vous devez le faire (généralement) pour éviter les effets secondaires indésirables étant déclenché ou le code courant qui peut jeter exceptions et même corrompre l'état de votre application.

Tip: le Subscription contient une propriété booléenne closed qui peut être utile dans certains cas. Pour HTTP, ceci sera défini lorsqu'il sera terminé. Aussi parfois, il peut être utile de définir une propriété _isDestroyed après la destruction d'un composant que subscribe peut vérifier pour décider ce qu'il ne faut pas exécuter.

8
répondu Simon_Weaver 2018-08-27 21:32:38

également avec le nouveau module HttpClient, reste le même comportement packages/common/http/src/jsonp.ts

7
répondu Ricardo Martínez 2018-02-20 12:18:55

vous ne devez pas vous désabonner des observables qui se remplissent automatiquement (E. G Http, appels). Mais il est nécessaire de se désabonner des observables infinis comme Observable.timer() .

4
répondu Misha Mykhalyuk 2018-07-04 14:59:39

RxJS observable sont fondamentalement associés et fonctionnent en conséquence vous l'souscrivez. Lorsque nous créons l'observable et le mouvement nous le complétons, observable se ferme automatiquement et se désabonne.

nous n'avons pas à invoquer explicitement la méthode de désabonnement.vous pouvez vérifier l'état de observable en utilisant la méthode fermée.

0
répondu Sachin Mishra 2018-08-12 11:39:35