Photo by Artem Sapegin on Unsplash

¡Conozcamos los Observables!

Mayra Rodriguez

--

Desde hace un par de años hemos empezado a conocer un poco sobre la programación reactiva o Reactive Programming, pero ciertamente muy pocas veces dedicamos el tiempo necesario para entender un poco más a profundidad un concepto o entender la teoría de muchas cosas que implementamos a diario en nuestro código.

Es por ello que decidí escribir éste post, no solo me siento recientemente atrapada por la programación reactiva, si no que para hablar de muchos conceptos más complejos y avanzados más adelante quiero que entendamos un poco cual es la base o el core de éste paradigma, conocido como Observable.

Conozcamos los conceptos básicos:

Reactive Programming

Es un paradigma de programación en la cual se centra en el manejo de data a través de streaming de datos. Así mismo, se centra en la propagación de cambios en tiempo real. (¿Pero para qué nos sirve esto?, más adelante les mostraré).

Reactive eXtensions (Rx)

Es una API que nos provee una buena documentación de cómo implementar Reactive Programming en nuestra plataforma, pero por supuesto, debe existir una librería o framework para integrarlo en nuestra tecnología. Para el caso de Angular y/o Javascript, la librería que se basa en Rx se llama RxJS. Algunas de las librerías o framework de otras plataformas son las siguientes:

Lenguajes y Framework que utilizan ésta API

RxJS

Como lo mencionaba anteriormente es la librería de Reactive Programming para Javascript. Está hecha con funciones puras lo que significa que no depende de otras librerías si no que está hecho con funciones nativas del lenguaje lo que garantiza rapidez, escalabilidad, mejor debugging o seguimiento de errores y mejor testing o pruebas, entre otros. Otras características de RxJS es que combina no solo el patrón del observador (Observer Pattern) si no también el del iterador (Iterator Pattern) por lo que usa funciones como las de los arrays o listas (map, filter, reduce, etc). Además (para el gusto de muchos) implementa la programación funcional (Functional Programming).

Pero bueno, ahora que ya entendemos un poco sobre los conceptos básicos ¡Conozcamos los Observables! (Ahora sí).

Observable

Los observables representan una colección de futuros valores o data, es decir, data que probablemente aún no estemos recibiendo.

Imaginemos una fábrica de helados:

Streaming de Helados :)

Inicialmente antes de que la maquina arranque a fabricar los helados, sabemos que tiene toda la mezcla lista para salir y a través del molde devolvernos uno a uno cada helado. No sabemos cuántos helados nos dará la maquina, pero probablemente sean muchos (y debemos estar preparados para ello). Ésta es la representación de un observable, un conjunto de N cantidad de helados que podremos recibir en un momento determinado.

Toda la arquitectura de la Programación Reactiva se centra en los Observables y ¿por qué?, por qué los observables tienen ciertas características resaltantes que lo diferencian de una función común e inclusive de su archienemigo; Las promesas o Promises (es broma, no son enemigos, solo quise sonar dramática).

Por ejemplo, las funciones solo pueden retornar un valor una sola vez, mientras que los observables pueden retornar o devolver un valor multiples veces. En el caso de las promesas, estas no son cancelables, mientras que los observables sí lo son, es decir, podemos desuscribirnos de un observable, lo que lo hace Lazy, es decir que podemos usarlo solo cuando lo necesitemos.

Si lo llevamos al ejemplo de los helados, no nos serviría de nada una fábrica de helados que solo fabrique un solo helado, o peor aún, que no podamos activar o desactivar la máquina que fabrica helados en ningún momento del día (OMG ¡What a disaster!)

Otra razón por la cual los Observables son el core de la Programación Reactiva es que los observables soportan multiples tipos de datos, no solo string, array, numbers si no también events, files, routes, ó helados (es broma). Quizás ahora no tenga mucho sentido esto, pero a medida que vamos implementando el patrón de diseño del observable podremos ir viendo la utilidad de que soporte multiples tipos de data.

Ejemplo:

En éste ejemplo creamos un observable que retorna 3 valores diferentes.

const observable = new Observable(subscriber => {   subscriber.next('Helado 1');
subscriber.next('Helado 2');
subscriber.next('Helado 3');
})

Sin embargo el observable no hace nada si no nos subscribimos a él (es como si no activáramos la máquina de helados).

Screenshot de la consola, vacía.

Subscribe & UnSubscribe

Para empezar a obtener los valores que retorna un observable debemos subscribirnos a él. El Subscribe es básicamente la forma en la que podemos ejecutar un observable.

De nuevo al ejemplo de los helados, pensemos un poco en cuando activamos o desactivamos la maquina que fabrica los helados, si no la activamos no saldrán más helados, sin embargo al momento de activarla empiezan a salir nuevamente.

El Unsubscribe es simplemente la forma en que nos desuscribimos al observable para que ya no recibamos más data. Tal como desactivar la maquina de helados.

Ejemplo:

Basado en el ejemplo anterior, al subscribirnos podemos ver en consola el valor que retorna el Observable.

const observable = new Observable(subscriber => {   subscriber.next('Helado 1');
subscriber.next('Helado 2');
subscriber.next('Helado 3');
});observable.subscribe((res) => { console.log(res); });
Información en consola una vez que nos subscribimos al observable.

Observer

Al momento de subscribirnos a un Observable debemos saber si recibimos exitosamente la data, si en su defecto falló o si ya no recibiremos más data en el futuro y se completó, para éste caso usamos los Observers.

Si al momento de que nuestra maquina de helado está encendida y empieza a fabricar helados, sucede un error, o queremos saber cuando terminó de fabricar los helados o simplemente queremos hacer algo con cada helado que nos devuelve, debemos usar el Observer.

Ejemplo:

En éste ejemplo vemos como no solo creamos en el Observer, el cual recibe el next en caso de recibir la data, el error en caso de que falle y el complete en caso de que se haya completado el observable.

Adicionalmente también, en la creación del observable le estamos indicando cuándo se completa a través del subscriber.complete().

import { Observable } from ‘rxjs’;const observable = new Observable(subscriber => {  subscriber.next('Helado 1');
subscriber.next('Helado 2');
subscriber.next('Helado 3');
subscriber.complete();
});const observer = {
next(x) { console.log(‘Salida:’ + x); },
error(err) { console.error(‘Ops! algo pasó: ‘ + err); },
complete() { console.log(‘Completó!’); }
};
observable.subscribe(observer);
Información que arroja la consola en éste caso

Operator

Y finalmente los operadores, son un conjunto de funciones que nos permitirán (principalmente) modificar la data que recibimos.

Helados modificados con una rica cobertura de chocolate

Ejemplo:

Para darte un ejemplo de los operadores usaré dos de los más comunes:

pipe: El cual permite combinar y usar otros operadores.

map: El cual recibe cada data del Observable y retorna una data que modifiquemos.

observable.pipe(
map(data => `${data} modificado :)`)).subscribe(observer);
La salida en una data modificada con el mensaje de `modificado :)`

Espero que te haya gustado éste post que hice con mucho cariño ❤

Para ver el ejemplo final puedes verlo a través de éste link.

--

--

Mayra Rodriguez

Google Developer Expert for Angular — Senior FullStack Engineer at Terminal Labs