que observables example ejemplo angular memory-leaks rxjs angular2-http

angular - example - ¿Es necesario darse de baja de los observables creados por los métodos Http?



subscribe angular 4 (8)

¿De qué están hablando?

OK, hay dos razones para darse de baja de cualquier observable. ¡Nadie parece estar hablando mucho sobre la muy importante segunda razón!

1) Limpiar recursos. Como otros han dicho, este es un problema insignificante para los observables HTTP. Simplemente se limpiará solo.

2) Evite que se ejecute el controlador de subscribe .

(Para HTTP, esto también cancelará la solicitud en el navegador, por lo que no perderá tiempo leyendo la respuesta. Pero en realidad eso es un aparte de mi punto principal a continuación).

La relevancia del número 2 dependerá de lo que haga su controlador de suscripción:

Si su función de controlador subscribe() tiene algún tipo de efecto secundario que no es deseado si cualquiera de las llamadas se cierra o elimina, entonces debe cancelar la suscripción (o agregar lógica condicional) para evitar que se ejecute.

Considere algunos casos:

1) Un formulario de inicio de sesión. Ingresas nombre de usuario y contraseña y haces clic en ''Iniciar sesión''. ¿Qué sucede si el servidor es lento y decide presionar Escape para cerrar el cuadro de diálogo? Probablemente asumirás que no has iniciado sesión, pero si la solicitud http regresó después de presionar escape, entonces aún ejecutarás cualquier lógica que tengas allí. Esto puede dar lugar a una redirección a una página de cuenta, una cookie de inicio de sesión no deseada o una variable de token configurada. Probablemente esto no sea lo que su usuario esperaba.

2) Un formulario de ''enviar correo electrónico''.

Si el controlador de subscribe para ''sendEmail'' hace algo como activar una animación ''Se envía su correo electrónico'', lo transfiere a una página diferente o intenta acceder a cualquier cosa que haya sido eliminada, puede obtener excepciones o comportamientos no deseados.

También tenga cuidado de no asumir que unsubscribe() significa ''cancelar''. Una vez que el mensaje HTTP está en curso, unsubscribe() NO cancelará la solicitud HTTP si ya ha llegado a su servidor. Solo cancelará la respuesta que vuelve a usted. Y el correo electrónico probablemente se enviará.

Si crea la suscripción para enviar el correo electrónico directamente dentro de un componente de la interfaz de usuario, probablemente desee darse de baja al deshacerse, pero si el correo electrónico lo envía un servicio centralizado que no es la interfaz de usuario, entonces probablemente no sea necesario.

3) Un componente angular que se destruye / cierra. Todos los observables http que aún se estén ejecutando en ese momento completarán y ejecutarán su lógica a menos que cancele su suscripción en onDestroy() . Si las consecuencias son triviales o no dependerá de lo que haga en el controlador de suscripción. Si intenta actualizar algo que ya no existe, puede recibir un error.

A veces puede tener algunas acciones que desearía si el componente se elimina, y otras no. Por ejemplo, tal vez tenga un sonido ''swoosh'' para un correo electrónico enviado. Probablemente desee que esto se reproduzca incluso si el componente estaba cerrado, pero si intenta ejecutar una animación en el componente, fallaría. En ese caso, una solución condicional adicional dentro de la suscripción sería la solución, y NO querrás cancelar la suscripción del http observable.

Entonces, en respuesta a la pregunta real, no, no necesita hacerlo para evitar pérdidas de memoria. Pero debe hacerlo (a menudo) para evitar que se desencadenen efectos secundarios no deseados al ejecutar código que pueda generar excepciones o corromper el estado de su aplicación.

Consejo: La Subscription contiene una propiedad booleana closed que puede ser útil en casos avanzados. Para HTTP, esto se establecerá cuando se complete. En Angular, puede ser útil en algunas situaciones establecer una propiedad ngDestroy en ngDestroy que puede ser verificada por su controlador de subscribe .

Consejo 2: si maneja varias suscripciones, puede crear un new Subscription() objeto Ad-hoc new Subscription() y add(...) cualquier otra suscripción, por lo que cuando cancele la suscripción de la principal, también cancelará la suscripción de todas las suscripciones agregadas.

¿Necesita darse de baja de las llamadas http de Angular 2 para evitar pérdidas de memoria?

fetchFilm(index) { var sub = this._http.get(`http://example.com`) .map(result => result.json()) .map(json => { dispatch(this.receiveFilm(json)); }) .subscribe(e=>sub.unsubscribe()); ...


Definitivamente deberías leer this artículo. Le muestra por qué siempre debe darse de baja incluso de http .

Si después de crear la solicitud pero antes de recibir una respuesta del back-end considera que el componente es innecesario y lo destruye, su suscripción mantendrá la referencia al componente, creando así la posibilidad de causar pérdidas de memoria.

Actualizar

La afirmación anterior parece ser cierta, pero de todos modos, cuando la respuesta vuelve, la suscripción http se destruye de todos modos


Entonces la respuesta es no, no lo haces. Ng2 lo limpiará solo.

La fuente del servicio Http, de la fuente de back-end Http XHR de Angular:

Observe cómo se ejecuta complete() después de obtener el resultado. Esto significa que en realidad se da de baja al finalizar. Entonces no necesitas hacerlo tú mismo.

Aquí hay una prueba para validar:

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); }; }

Como se esperaba, puede ver que siempre se da de baja automáticamente después de obtener el resultado y terminar con los operadores observables. Esto sucede en un tiempo de espera (# 3) para que podamos verificar el estado del observable cuando todo esté hecho y completado.

Y el resultado

Por lo tanto, no existiría ninguna fuga ya que Ng2 baja automáticamente.

Es bueno mencionar: este Observable se clasifica como finite , al contrario que el Observable infinite que es un flujo infinito de datos que se puede emitir como el escucha de click DOM, por ejemplo.

GRACIAS, @rubyboy por su ayuda en esto.


Llamar al método para cancelar la unsubscribe es más bien cancelar una solicitud HTTP en curso, ya que este método llama al abort en el objeto XHR subyacente y elimina los escuchas en los eventos de carga y error:

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

Dicho esto, unsubscribe elimina a los oyentes ... Por lo tanto, podría ser una buena idea, pero no creo que sea necesario para una sola solicitud ;-)

Espero que te ayude, Thierry


Los observables RxJS están básicamente asociados y funcionan en consecuencia, lo suscribe. Cuando creamos el observable y el movimiento que lo completamos, el observable se cierra y cancela automáticamente.

Trabajan de la misma manera que los observadores pero en un orden bastante diferente. La mejor práctica es cancelar la suscripción cuando el componente se está destruyendo. Posteriormente podríamos hacerlo, por ejemplo. this. $ manageSubscription.unsubscibe ()

Si hemos creado el observable como la sintaxis mencionada a continuación, como

** return new Observable ((observador) => {** // Hace observable en estado frío ** observer.complete () **}) **


No debe darse de baja de los observables que se completa automáticamente (por ejemplo, Http, llamadas). Pero es necesario darse de baja de infinitos observables como Observable.timer() .


También con el nuevo módulo HttpClient, sigue siendo el mismo comportamiento


Darse de baja es imprescindible si desea un comportamiento determinista en todas las velocidades de red.

Imagine que el componente A se representa en una pestaña: hace clic en un botón para enviar una solicitud ''OBTENER''. La respuesta tarda 200 ms en volver. Por lo tanto, puede cerrar la pestaña en cualquier momento sabiendo que la máquina será más rápida que usted y la respuesta http se procesará y se completará antes de que se cierre la pestaña y se destruya el componente A.

¿Qué tal en una red muy lenta? Al hacer clic en un botón, la solicitud ''OBTENER'' tarda 10 segundos en recibir su respuesta, pero 5 segundos después de esperar, decide cerrar la pestaña. Eso destruirá el componente A para ser recolectado como basura en un momento posterior. ¡Espera un minuto! , no cancelamos la suscripción; ahora, 5 segundos después, vuelve una respuesta y se ejecutará la lógica en el componente destruido. Esa ejecución ahora se considera out-of-context y puede dar lugar a muchas cosas, incluido un rendimiento muy bajo.

Por lo tanto, la mejor práctica es usar takeUntil() y cancelar la suscripción de llamadas http cuando se destruye el componente.

import { Component, OnInit, OnDestroy } from ''@angular/core''; import { HttpClient } from ''@angular/common/http''; import { Subject } from ''rxjs''; import { takeUntil } from ''rxjs/operators''; interface User { id: string; name: string; age: number; } @Component({ selector: ''app-foobar'', templateUrl: ''./foobar.component.html'', styleUrls: [''./foobar.component.scss''], }) export class FoobarComponent implements OnInit, OnDestroy { private user: User = null; private destroy$ = new Subject(); constructor(private http: HttpClient) {} ngOnInit() { this.http .get<User>(''api/user/id'') .pipe(takeUntil(this.destroy$)) .subscribe(user => { this.user = user; }); } ngOnDestroy(): void { this.destroy$.next(); // trigger the unsubscribe this.destroy$.complete(); // finalize & clean up the subject stream } }