Operadores básicos en RXJS
Alex Córdoba
Posted on April 21, 2023
Un operador es una función que se usa en un observable y controla y emite solo la información que nos interesa de la forma en que la necesitamos.
map
Nos permite transformar o extraer lo que emite el observable en algo diferente, manteniendo la estructura del flujo original. map
es uno de los operadores más comunes y poderosos en RxJS, y se utiliza ampliamente para realizar transformaciones en los datos emitidos por un observable.
La sintaxis básica de map es la siguiente:
observable$.pipe(
map(valor => nuevoValor)
)
Donde observable$ es el flujo de datos observable del cual se desean transformar los valores, y valor => nuevoValor es una función de transformación que toma cada valor emitido por el observable y devuelve un nuevo valor transformado.
Miremos su grafica de canicas:
ejemplo:
Transformación de valores: La función de transformación que se pasa como argumento a map es aplicada a cada valor emitido por el observable. Esta función toma el valor original y devuelve un nuevo valor transformado. Por ejemplo:
const numeros$ = of(1, 2, 3, 4, 5); // Observable que emite los números del 1 al 5
numeros$.pipe(
map(numero => numero * 2) // Transforma cada número emitido por el observable multiplicándolo por 2
).subscribe(resultado => console.log(resultado));
El resultado de este código sería imprimir en la consola: 2, 4, 6, 8, 10, que son los valores originales multiplicados por 2.
filter
El operador filter
es una función de filtrado que se utiliza para emitir solo aquellos elementos de un flujo de datos observable que cumplan con una condición especificada. En otras palabras, filter permite seleccionar elementos de un observable que satisfagan una condición dada y descartar aquellos que no la cumplan.
La sintaxis básica de filter es la siguiente:
observable$.pipe(
filter(condicion)
)
Donde observable$ es el flujo de datos observable del cual se desean filtrar los elementos, y condicion es una función de predicado que especifica la condición que debe cumplir cada elemento emitido para ser seleccionado.
filter
permite utilizar cualquier función de predicado que devuelva un valor booleano para evaluar la condición de filtrado. Esto proporciona una gran flexibilidad para especificar condiciones complejas basadas en cualquier propiedad o característica de los elementos emitidos por el observable.
Esta es su grafica de canicas:
veamos un ejemplo:
const personajes = [
{
tipo: 'heroe',
nombre: 'Batman',
},
{
tipo: 'heroe',
nombre: 'Robin',
},
{
tipo: 'villano',
nombre: 'Joker',
},
];
from(personajes)
.pipe(filter((personaje) => personaje.tipo === 'heroe'))
.subscribe(console.log);
El resultado de este código sería imprimir en la consola {tipo: "heroe", nombre: "Batman"}, {tipo: "heroe", nombre: "Robin"}
, que son los personajes que cumplen con la condición especificada en la función de predicado.
Una característica importante de filter es que los elementos que no cumplen con la condición especificada en la función de predicado no se emiten en el resultado del observable. Esto significa que solo los elementos que satisfacen la condición son emitidos, y los demás son ignorados y no se propagan en el flujo de datos.
tap
El operador tap es un operador de utilidad que permite realizar acciones secundarias o efectos secundarios en los elementos que fluyen a través de un flujo de datos observable, sin afectar la emisión o transformación de los elementos en sí. Es una herramienta poderosa para depurar, registrar o ejecutar lógica adicional en un flujo de datos observable sin modificar su comportamiento.
La sintaxis básica de tap es la siguiente:
observable$.pipe(
tap(funcionEfecto)
)
Donde observable$ es el flujo de datos observable al cual se desea aplicar el efecto secundario, y funcionEfecto es una función que se ejecuta para cada elemento emitido por el observable, sin modificar el elemento en sí, y puede realizar cualquier lógica adicional deseada.
El operador tap
ejecuta la función de efecto especificada para cada elemento emitido por el observable. La función de efecto puede ser una función con cualquier lógica adicional que desees realizar, como imprimir en la consola, registrar eventos, enviar datos a un servidor, etc. La función de efecto no modifica el elemento en sí, solo realiza acciones adicionales sobre él.
Aqui su grafica de canicas:
const numeros$ = of(1, 2, 3, 4, 5); // Observable que emite números
numeros$.pipe(
tap(numero => console.log(`Número emitido: ${numero}`)) // Imprime en la consola cada número emitido
).subscribe();
El resultado de este código sería imprimir en la consola: Número emitido: 1, Número emitido: 2, Número emitido: 3, Número emitido: 4, Número emitido: 5, registrando cada número emitido por el observable.
Es importante tener en cuenta que tap no modifica los elementos emitidos por el observable. La función de efecto se ejecuta en paralelo con la emisión de los elementos, sin modificarlos. Si deseas modificar los elementos emitidos, deberás utilizar otros operadores de transformación de datos en combinación con tap.
const numeros$ = of(1, 2, 3, 4, 5); // Observable que emite números
numeros$.pipe(
tap(x => console.log),
map(val => val * 10)
).subscribe(val => console.log)
El resultado seria 10, 20, 30, 40, 50
reduce
El operador reduce
es un operador de transformación que permite reducir una secuencia de valores en un solo valor, Este operador recibe una función de acumulación como argumento y aplica dicha función a los valores emitidos por la secuencia de entrada.
La función de acumulación toma dos argumentos: el acumulador y el valor actual emitido por la secuencia de entrada. El acumulador es el valor acumulado hasta el momento, mientras que el valor actual es el valor emitido por la secuencia en ese instante. La función de acumulación debe devolver un valor que se usará como el nuevo valor del acumulador.
La forma general del operador reduce en rxjs es la siguiente:
reduce(accumulator: function, seed?: any): Observable
El argumento accumulator
es la función de acumulación que se aplicará a los valores emitidos por la secuencia. El argumento seed
es un valor opcional que se utilizará como el valor inicial del acumulador. Si se proporciona seed
, la función de acumulación se aplicará a seed
y al primer valor emitido por la secuencia. Si no se proporciona seed
la función de acumulación se aplicará al primer y segundo valor emitidos por la secuencia.
El operador reduce devuelve un Observable
que emite un solo valor: el resultado final de la acumulación. Este valor se emite cuando la secuencia de entrada se completa.
Grafica de canicas:
Aquí hay un ejemplo:
import { of } from 'rxjs';
import { reduce } from 'rxjs/operators';
const source = of(1, 2, 3, 4, 5);
const example = source.pipe(
reduce((acc, curr) => acc + curr)
example.subscribe(console.log) // salida: 15
En el ejemplo anterior, creamos un Observable
que emite los valores 1, 2, 3, 4, 5. Luego, aplicamos el operador reduce
con una función de acumulación que suma los valores. El resultado final de la acumulación es 15, que se emite cuando la secuencia de entrada se completa.
scan
El operador scan
es un operador de transformación que es similar al operador reduce
, pero en lugar de emitir un solo valor al final de la secuencia, emite un valor acumulado en cada paso de la secuencia.
La función de acumulación utilizada en scan
es similar a la utilizada en reduce
ya que toma dos argumentos: el acumulador y el valor actual emitido por la secuencia de entrada. La diferencia es que la función de acumulación devuelve el valor acumulado en lugar de devolver el valor que se usará como el nuevo valor de acumulador. En otras palabras scan
emite el valor acumulado después de aplicar la función de acumulación a cada valor de la secuencia de entrada.
la forma general del operador scan
es la siguiente:
scan(accumulator: function, seed?: any): Observable
El argumento accumulator
es la función de acumulación que se aplicará a los valores emitidos por la secuencia. El argumento seed
es un valor opcional que se utilizará como el valor inicial del acumulador. Si se proporciona seed
, la función de acumulación se aplicará a seed
y al primer valor emitido por la secuencia. Si no se proporciona seed
la función de acumulación se aplicará al primer y segundo valor emitidos por la secuencia.
El operador scan
devuelve un Observable
que emite el valor acumulado después de aplicar la función de acumulación a cada valor de la secuencia de entrada.
Esta es su grafica de canicas:
Por ejemplo:
import { of } from 'rxjs';
import { scan } from 'rxjs/operators';
const source = of(1, 2, 3, 4, 5);
const example = source.pipe(
scan((acc, curr) => acc + curr)
example.subscribe(console.log) // salida: 1, 3, 6, 10, 15
En este ejemplo creamos un Observable
que emite los valores 1, 2, 3, 4, 5 y luego aplicamos el operador scan
con una función de acumulación que suma los valores. El valor acumulado después de aplicar la función de acumulación a cada valor de la secuencia de entrada se emite a cada paso de la secuencia. Es este caso, la salida es 1, 3, 6, 10, 15.
take
El operador take
permite emitir los primero n valores emitidos por la secuencia de entrada. Una vez que se han emitido n valores, la secuencia se completa automáticamente y se detiene.
La sintaxis básica de take es la siguiente:
take(count: number): Oberservable
El argumento count
especifica el número de valores que se deben emitir antes de completar la secuencia.
Esta es su grafica de canicas:
Aquí hay un ejemplo de cómo usar el operador take
en Rxjs
import { interval } from 'rxjs'
import { take } from 'rxjs/operators';
const source = interval(1000);
const example = source.pipe(
take(5)
);
example.subscribe(console.log) // salida: 0, 1, 2, 3, 4
En este ejemplo, creamos un Observable
que emite un valor cada segundo utilizando el operador interval
. Luego, aplicamos el operador take
con un argumento de 5, lo que significa que solo se emitirán los primeros 5 valores emitidos por la secuencia. La salida del subscribe
es 0, 1, 2, 3, 4.
EL operador take
también se puede combinar con otros operadores de rxjs, como filter
, map
, mergeMap
, etc. para manipular y limitar los valores emitidos por la secuencia de entrada.
Posted on April 21, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.