Cómo eliminar una suscripción a un observable, desde el observador, necesario cuando el elemento se destruye para no dejar en memoria la suscripción.
En este artículo vamos a estudiar una práctica fundamental con los observables de Angular (incorporados mediante la librería RxJS), que consiste en dar de baja las suscripciones cuando ya no tiene sentido que permanezcan en memoria.
Enseguida explicaré el motivo de la importancia de este paso, que complementa las explicaciones de artículos anteriores del Manual de Angular. De hecho, si leíste el pasado capítulo de este manual "Práctica con Observables" nos dejamos pendiente explicar cómo completar el flujo mediante el paso de dar de baja la suscripción a los eventos del observable.
Este artículo de paso servirá para seguir aprendiendo cosas de Angular en general, como el uso del método ngOnDestroy(), que nos permite ejecutar código cuando un componente deja de existir. Así que vamos con ello!
Por qué es importante eliminar las suscripciones a los observables
Al trabajar con observables creamos suscripciones a un flujo de datos o eventos. Esas suscripciones permanecen en memoria el tiempo que sean necesario, que habitualmente debe ser el tiempo en el que un componente exista. Si el componente que está escuchando eventos o datos mediante una suscripción deja de existir, no tiene sentido que la suscripción permanezca ejecutándose en el sistema. Angular en muchas ocasiones se encarga de eliminar las suscripciones a los observables, pero en otras ocasiones podría no hacerlo y si somos suficientemente meticulosos, deberíamos realizarlo por nuestra cuenta con un poco de código.
En este punto puede que te preguntes ¿Cómo es posible que el componente deje de existir? La respuesta puede ser bien obvia, pero sólo se entenderá con el sistema de routing en mente.
En el sistema de routing puede ocurrir que estemos viendo una pantalla u otra de la aplicación, según la ruta consumida. En cada ruta generalmente hay un componente que se encarga de mostrar aquella pantalla o vista que se tiene que mostrar al usuario. Cuando el usuario pasa a otra ruta de la aplicación, ocurre que el componente se destruye, y se genera un nuevo componente en su lugar, con la vista de la nueva pantalla.
Así pues, en la destrucción de un componente, al pasar de una ruta a otra, es esencial que las suscripciones existentes se eliminen de la memoria.
Método ngOnDestroy()
El método ngOnDestroy() pertenece al ciclo de vida de los componentes de Angular. Es el lugar adecuado para realizar las acciones necesarias a ejecutar con la destrucción de un componente.
Es muy parecido al conocido ngOnInit(), pero se ejecuta cuando un componente deja de existir.
Para usar este método tenemos que implementar la interfaz OnDestroy. Y por supuesto, dentro de la implementación del componente, se debe definir el método ngOnDestroy(), para cumplir el contrato definido por esta interfaz.
Primero tenemos que asegurarnos de importar la interfaz OnDestroy, desde "@angular/core".
import { Component, OnInit, OnDestroy } from '@angular/core';
Una vez importada, ya podemos implementarla, de la siguiente manera.
export class MiComponent implements OnInit, OnDestroy {
ngOnInit() {
// acciones de inicialización
}
ngOnDestroy() {
// acciones de destrucción
}
}
Cómo eliminar una suscripción a un observable
Esta parte incluye varios pasos a realizar, que pasamos a resumir.
1.- Importar la declaración de suscripción de un observable
Vamos a tener que almacenar la suscripción en algún lugar y para poder tiparla convenientemente vamos a importar la declaración de "subscription definida por RxJS.
import { Subscription } from 'rxjs/Subscription';
2.- Declarar la suscripción como propiedad del componente
Entre las propiedades del componente vas a tener que declarar la suscripción, para disponer de ella cuando sea necesaria. Es de tipo "Subscription".
clientesSubscription: Subscription;
3.- Guardarnos la suscripción en el paso de su creación
Usamos la propiedad creada en el paso anterior para almacenar el objeto de la suscripción. Simplemente asignamos el valor que nos devuelve el método suscribe() sobre el observable. Recuerda que la suscripción en nuestro ejemplo la habíamos creado en ngOnInit(), después de haber solicitado el observable al servicio.
ngOnInit() {
this.clientes$ = this.clientesService.getClientes$();
this.clientesSubscription = this.clientes$.subscribe(clientes => this.clientes = clientes);
}
4.- Eliminamos la suscripción al destruirse el elemento
Ya por fin, una vez el componente se destruya, realizamos el paso más relevante, que es eliminar la suscripción. Lo hacemos en el método ngOnDestroy y usamos la propiedad donde habíamos guardado la suscripción. Esa suscripción tiene un método llamado unsubscribe() que hace la tarea deseada.
ngOnDestroy() {
this.clientesSubscription.unsubscribe();
}
Con esto ya hemos solucionado la necesidad de eliminar la suscripción al observable. Ahora estamos seguros de que no se quedará colgada, ocupando espacio en la memoria, al destruirse el componente que la utilizaba.
No obstante, hay que decir que este componente no usaba el sistema de routing y no había modo de ser destruido durante la vida de la aplicación, por lo que en realidad este paso no era necesario para este ejemplo en concreto. Aunque tampoco es mala idea ser cuidadosos y colocar un código que produzca un componente más correcto y capaz de funcionar en todas partes sin problemas. De hecho, si ahora implementamos un sistema de routing y usamos este componente, se comportará perfectamente en su función, no dejando colgada en memoria la suscripción al observable.
El código de esta práctica, tal como la hemos dejado después de este artículo, lo puedes ver en GitHub: https://github.com/midesweb/ej_facturacion_angular/tree/48427d9a86c9dc83dbaf06bc9b72e351039287d8
Miguel Angel Alvarez
Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...