DEV Community

Alex Córdoba
Alex Córdoba

Posted on

Operadores básicos en RXJS

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)
)
Enter fullscreen mode Exit fullscreen mode

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:

Image description

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

Enter fullscreen mode Exit fullscreen mode

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)
)
Enter fullscreen mode Exit fullscreen mode

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:

Image description

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);
Enter fullscreen mode Exit fullscreen mode

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)
)
Enter fullscreen mode Exit fullscreen mode

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:

Image description

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

Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:

Image description

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:

Image description

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

El argumento count especifica el número de valores que se deben emitir antes de completar la secuencia.

Esta es su grafica de canicas:

Image description

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
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)