Programación Reactiva en Dart — III

Manipulando Streams

Alfredo Bautista Santos
DotTech

--

Photo by Markus Winkler on Unsplash

Introducción

¡Hola a todos! En esta última entrega vamos a descubrir el potencial del paquete RxDart. Veremos qué significan sus siglas Rx, las diferencias entre su API con la que provee el propio lenguaje para trabajar con Streams y un pequeño ejemplo de uso de la biblioteca.

Logo de ReactiveX

ReactiveX, según la documentación oficial, se refiere a la combinación de diferentes modelos de varios patrones de programación como el Observer pattern.

Rx es la abreviatura que utilizan todas las bibliotecas que adaptan la API, definida en la web de reactivex.io, al lenguaje que estemos usando. En nuestro caso, el lenguaje Dart.

Cómo podemos ver en su página oficial, hay muchos paquetes para poder usar la programación reactiva con los mismos métodos y objetos en diferentes lenguajes.

Implementación en Dart

El paquete oficial que implementa esta funcionalidad en Dart es RxDart. Podemos ver cómo es un paquete con el sello de “Flutter Favorite” por lo que goza de gran aceptación en la comunidad y tiene una estabilidad garantizada.

En una de sus últimas versiones, la 0.23, comienza a usar las extensiones. Si no conocéis la extensiones en Dart, podéis echar un vistazo a esta documentación. Debido a este cambio, en las últimas versiones se deja de usar la clase Observable para utilizar las nativas del lenguaje con las extensiones.

Podemos comenzar a usar esta biblioteca únicamente añadiéndola en nuestro pubspec.yaml en la última versión estable.

Observables vs Dart Streams

Si sueles usar la API de Rx en otros lenguajes, tu adaptación a este paquete será mínima. En la documentación oficial podemos ver una tabla que resume perfectamente las diferencias entre usar observables de Rx y streams de Dart.

Comparación de Observables de Rx con streams de Dart

Como podemos ver, hay muchas similitudes entre los dos objetos, aunque también alguna diferencia importante.

Manos a la obra

Ahora que ya tenemos la biblioteca lista para usar, vamos a ver algunos de sus métodos más interesantes para aumentar las funcionalidades de nuestros streams.

Comencemos con los diferentes constructores que nos ofrece la biblioteca para poder crear streams a partir de distintos orígenes de datos. Tenemos un montón de constructores que nos permiten configurar el stream resultante. Veamos algunos de los que pueden ser más interesantes:

  • RaceStream: Nos retorna un Stream con el primer dato que haya sido mandado por los streams que recibe su constructor. Puede ser útil para mandar varias peticiones a la vez y solo quedarnos con la más rápida.
  • TimerStream: Nos permite crear un Stream que enviará el valor enviado en el constructor dentro del tiempo indicado en el segundo parámetro del constructor usando la clase Duration.
  • RepeatStream: Crea un Stream que será reconstruido las veces que se le indiquen en el constructor; como primer parámetro debemos pasar una función que retorne un Stream.
  • ForkJoinStream: Recibe una lista de streams y retorna uno con el último valor de cada Stream. Dependiendo del constructor que usemos podemos retornar los valores sin procesar o podemos transformar los valores antes de ser enviados.

Ahora que hemos visto cómo crear streams mediante objetos de la biblioteca, vamos a ver qué métodos nos ofrece para trabajar con estos streams. Para no entrar en cada método, ya que son bastantes, os dejo la documentación aquí para que podáis ver qué hace cada método. Para entenderlos mejor, vamos a poner en práctica algunos de estos métodos.

Mejorando nuestra factoría

Vamos a implementar nuevas funcionalidades a nuestra factoría de chistes. En este caso, como estamos usando Dart en línea de comandos, pediremos que se pulse 4 veces para generar un chiste. Usaremos el método bufferCount para que mande una petición cuando el Stream haya recibido 4 pulsaciones desde la consola.

Usando el método bufferCount

Con un resultado similar al siguiente:

Con este ejemplo hemos forzado a que nuestro Stream contenga una cantidad de datos concretos para permitir que se propague un evento. Ahora vamos a ver el caso contrario, ¿Cómo limitamos los eventos producidos por un Stream? Para este uso tenemos debounce, que puede recibir como parámetro una ventana o window que se refiere a una cantidad de tiempo que viene dada por el tiempo que se demore en terminar el proceso introducido por parámetros.

En este caso vamos a usar debounceTime, ya que en este caso solo queremos que se pida un chiste cada 5 segundos, para que el usuario no pueda sobrecargar la API pidiendo sin límite.

Usando el método debounceTime

Y el resultado:

Incluso podemos dejar un margen de tiempo entre el momento en que recibimos la señal del Stream y la petición a la API; en este caso podemos usar delay que recibe un Duration como parámetro. Este caso es útil cuando queremos informar al usuario de que ha accionado la petición pero que se procesará mas tarde:

Usando el método delay

Y su resultado final:

Podemos seguir usando muchos más de los métodos que nos ofrece la biblioteca, aunque creo que están bastante bien explicados en su documentación y son bastante intuitivos.

Os dejo por aquí todo el listado de métodos para trabajar con streams de esta biblioteca.

Conclusión

Como podemos ver, esta biblioteca nos ofrece muchos métodos y funcionalidades que nos permiten trabajar con streams de una manera mucho más cómoda. Aunque en el caso de Dart, con el buen soporte asíncrono que incorpora, no es estrictamente necesario usar bibliotecas de terceros.

Bajo mi punto de vista, si empiezas a usar los streams en Dart sin haber pasado por otro lenguaje, te recomiendo usar la API nativa, que es más que suficiente en muchos casos.

Por otro lado, si sueles usar la biblioteca en otros lenguajes como JavaScript, por comodidad, puede ser interesante usar esta biblioteca para no tener que aprender conceptos nuevos y métodos que ya has usado anteriormente.

Con este último artículo, cerramos la saga de Programación Reactiva en Dart, si os ha parecido interesante, podéis dejar vuestro feedback y quizás podemos crear otra serie aplicando estos conceptos de reactividad en UI con Flutter.

Por ultimo dejo os mi twitter dónde me encontraréis hablando sobre tecnología en general pero sobre todo Flutter 💙

¡Un saludo y hasta la próxima!

--

--

Alfredo Bautista Santos
DotTech
Writer for

Sysadmin and web developer. Co-organizer of GDGMarbella & FlutterConf in Marbella, Spain. Flutter enthusiastic.