DEV Community

Alex Córdoba
Alex Córdoba

Posted on

Operadores no tan comunes de Rxjs

Después de dar un vistazo a los operadores comunes en Rxjs, esta vez es el turno de algunos operadores que no son tan comunes, tal vez desconocidos por algunos devs, pero muy utiles a la hora de agregar un comportamiento a nuestros Observables.

first

El operador first es un operador de filtrado que emite solo el primer valor que se emite en la secuencia de entrada y luego completa la secuencia.
También es posible especificar una condición opcional para determinar el primero valor que se emite.

La forma general del operador first es la siguiente:

first(predicate?: function): Observable
Enter fullscreen mode Exit fullscreen mode

El argumento predicate es una función que se usa para determinar el primero valor que se emite en la secuencia. Si no se proporciona ninguna función predicate el operador first emitirá el primero que se emita en la secuencia, teniendo el mismo comportamiento como si usáramos el operador take(1).

aqui hay un ejemplo:

import { interval } from 'rxjs'
import { first } from 'rxjs/operators';

const source = from([1, 2, 3, 4, 5]);

const example - source.pipe(
 first(x => x > 2)
);

example.subscribe(console.log) // salida: 3
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 first con una función predicate que devuelve true para el primer valor que sea mayor que 2. El primer valor que se emite en la secuencia que satisface la condición es 3, por lo que esa es la salida del subscribe.

Es importante tener en cuenta que take completará la secuencia después de emitir el primer valor, por lo que cualquier valor adicional que se emita después del primero valor se descartará. Si no se emite ningún valor que satisfaga la condición, el Observable resultante no emitirá ningún valor.

takeWhile

El operador takeWhile es un operador de filtrado que toma los valores emitidos por un Observable hasta que se produce un valor que no satisface una condición especificada.

La forma general del operador takeWhile es la siguiente:

takeWhile(predicate?: function, inclusive?: boolean): Observable
Enter fullscreen mode Exit fullscreen mode

El argumento predicate es una función que se utiliza para evaluar cada valor emitido por el Observable. Si el valor emitido satisface la condición especificada, se incluirá en el resultado. Si el valor no satisface la condición, la suscripción se completará y se dejará de emitir valores.

El argumento opcional inclusive se utiliza para incluir o excluir el valor que no cumple la condición especificada. Si inclusive es true, el valor que no cumple la condición se incluirá en la salida. Si inclusive es false el valor que no cumple la condición se excluye de la salida.

Por ejemplo:

import { of } from 'rxjs'
import { takeWhile } from 'rxjs/operators';

const source = of(1, 2, 3, 4, 5);

const example - source.pipe(
 takeWhile(x => x < 4)
);

example.subscribe(console.log) // salida: 1, 2, 3
Enter fullscreen mode Exit fullscreen mode

En este ejemplo, creamos un Observable que emite los valores 1, 2, 3, 4, 5, luego aplicamos el operador takeWhile con una función predicate que evalúa si cada valor emitido es menor que 4. El operador takeWhile incluirá los valores 1, 2 y 3 pero detendrá la emisión de valores después de que se emita el valor 4 que no cumple la condición.

También es posible usar el argumento opcional inclusive para incluir o excluir el valor que no cumple la condición especificada. Por ejemplo:

import { of } from 'rxjs'
import { takeWhile } from 'rxjs/operators';

const source = of(1, 2, 3, 4, 5);

const example - source.pipe(
 takeWhile(x => x < 4, true)
);

example.subscribe(console.log) // salida: 1, 2, 3, 4
Enter fullscreen mode Exit fullscreen mode

Donde en este caso el valor 4 a pesar de que no cumple la condición sera emitido por el por el Observable y detendrá la emisión de valores después de que se emita el valor 5 que no cumple la condición.

takeUntil

El operador takeUntil es un operador de finalización que emite valores de un Observable hasta que se emite un evento desde otro Observable.

La forma general del operador takeWhile es la siguiente:

takeUntil(notifier: Observable): Observable
Enter fullscreen mode Exit fullscreen mode

El argumento notifier es un Observable que se utiliza para emitir un evento que indica que la emisión del Observable de origen debe finalizar. Cuando el notifier emite un valor o completa, el Observable de origin se completa y ya no se emiten mas valores.

Esta seria su grifa de canicas:

Image description

Aquí hay un ejemplo:

import { interval, timer } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

const source = interval(1000);
const stopTimer = timer(5000);

const example = source.pipe(
 takeUntil(stopTimer)
);

example.subscribe(console.log) // salida: 0, 1, 2, 3, 4
Enter fullscreen mode Exit fullscreen mode

En este ejemplo, creamos un Observable que emite valores cada segundo utilizando interval(1000), luego, creamos un Observable que completa después de 5 segundos utilizando timer(5000). Finalmente, aplicamos el operador takeUntil con el notifier stopTimer que completará la emisión del Observable de origin después de 5 segundos.

El resultado es que solo se emiten los primeros 5 valores del Observable de origen, ya que la emisión se detiene después de que el notifier stopTimer emite un valor y completa.

También podemos usar otros Observable como notifier para finalizar la emisión del Observable de origen, como un botón pulsado, una respuesta de una API, una conexión de red que se interrumpe, etc.

skip

El operador skip se utiliza para omitir los primeros elementos de un Observable y emitir los restantes.

La forma general del operador skip es la siguiente:

skip(count: number): Observable
Enter fullscreen mode Exit fullscreen mode

El argumento count es un número entero que indica el número de elementos que se deben omitir antes de comenzar a emitir elementos.

Esta es la grafica de canicas para el operador skip:

Image description

Aqui un ejemplo:

import { of } from 'rxjs';
import { skip } from 'rxjs/operators';

const source = of(1, 2, 3, 4, 5);
const example = source.pipe(skip(3));

example.subscribe(console.log); // salida: 4, 5

Enter fullscreen mode Exit fullscreen mode

En este ejemplo creamos un Observable que emite los valores 1, 2, 3, 4, 5 utilizando of(1, 2, 3, 4, 5) luego aplicamos el operador skip con un valor de 3, lo que significa que se omitirán los primeros 3 valores. La salida del Observable resultante es 4 y 5.

También podemos usar expresiones lógicas más complejas para determinar qué elementos se deben omitir. Por ejemplo, podríamos usar una expresión lambda que devuelve verdadero o falso en función de las propiedades de los elementos.

Es importante tener en cuenta que si el número de elementos a omitir es mayor o igual que el número total de elementos en el Observable, el Observable resultante sera vacío

distinct

El operador distinct se utiliza para emitir solo los valores únicos de un Observable omitiendo los valores que se han emitido previamente.

la forma general del operador distinct es la siguiente:

distinct(keySelector?: (value: T) => K, flushes?: Observable<any>): Observable<T>
Enter fullscreen mode Exit fullscreen mode

El argumento opcional keySelector es una función que se utiliza para seleccionar una clave única para cada elemento. Si no se proporciona una función keySelector se utiliza el propio valor como clave.

El argumento opcional flushes es un Observable que se utiliza para limpiar la caché de valores previamente emitidos.

Tomemos este ejemplo:

import { of } from 'rxjs';
import { distinct } from 'rxjs/operators';

const source = of(1, 2, 3, 1, 2, 4, 5, 3);
const example = source.pipe(distinct());

example.subscribe(console.log); // salida: 1, 2, 3, 4, 5
Enter fullscreen mode Exit fullscreen mode

En este ejemplo creamos un Observable que emite los valores 1, 2, 3, 1, 2, 4, 5, 3 utilizando of(1, 2, 3, 1, 2, 4, 5, 3) luego, aplicamos el operador distinct que omitirá los valores duplicados y emitirá solo los valores únicos. La salida del Observable resultante es 1, 2, 3, 4, 5.

También podemos usar la función keySelector para seleccionar una clave única basada en alguna propiedad o característica de los elementos. Por ejemplo, si tenemos un Observable que emite objetos de usuario con una propiedad id, podemos usar la función keySelector para emitir solo los objetos de usuario con id único:

import { of } from 'rxjs';
import { distinct } from 'rxjs/operators';


const users = [
 { id: 1, name: 'Alice },
 { id: 2, name: 'Bob },
 { id: 1, name: 'Charlie },
 { id: 3, name: 'David },
 { id: 2, name: 'Eve }
]
const source = of(users);
const example = source.pipe(distinct(user => user.id));

example.subscribe(console.log); // salida: { id: 1, name: 'Alice}, { id: 2, name 'Bob' }, { id: 3, name: 'David' }
Enter fullscreen mode Exit fullscreen mode

En el ejemplo creamos un Observable que emite los objetos de usuario definidos en el array users. Luego, aplicamos el operador distinct con una función keySelector que selecciona la propiedad id de cada objeto de usuario como clave única. La salida del Observable resultante es solo los objetos de usuario con id único: { id: 1, name: 'Alice}, { id: 2, name 'Bob' }, { id: 3, name: 'David' }.

Es importante tener en cuenta que el operador distinct utiliza el cache interna para almacenar los valores emitidos previamente y determinar si un valor es único o no. Esto puede causar problemas de rendimiento si el Observable emite.
También es importante resaltar que el operador distinct utiliza el operador de equidad de triple igual === para comparar el valor emitido.

distinctUntilChanged

El operador distinctUntilChanged se utiliza para emitir solo los valores que no son iguales al valor anterior emitido por el Observable, es decir, si un valor se ha emitido previamente y es igual al valor actual, el valor actual se omite y no se emite.

La forma general del operador distinctUntilChanged es la siguiente:

distinctUntilChanged(compareFn?: (x: T, y: T) => boolean): MonoTypeOperatorFunction<T>
Enter fullscreen mode Exit fullscreen mode

El argumento opcional compareFn es una función que se utiliza para comparar dos valores y determinar si son iguales o no. Si no se proporciona una función compareFn, se utiliza el operador === para comparar valores.

Por ejemplo:

import { of } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators';

const source = of(1, 1, 2, 3, 3, 3, 4, 4, 5);
const example = source.pipe(distinctUntilChanged());

example.subscribe(console.log); // salida: 1, 2, 3, 4, 5
Enter fullscreen mode Exit fullscreen mode

En este ejemplo creamos un Observable que emite los valores 1, 1, 2, 3, 3, 3, 4, 4, 5 utilizando al función of de rxjs, luego aplicamos el operador distinctUntilChanged que omitirá los valores duplicados y emitirá solos los valores que no son iguales al valor anterior emitido. La salida del Observable resultante es 1, 2, 3, 4, 5.

También podemos usar la función compareFn para personalizar la comparación de valores. Por ejemplo si tenemos un Observable que emite objetos de usuario con una propiedad name, podemos usar la función compareFn para omitir los objetos de usuario con el mismo nombre:

import { of } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators';


const users = [
 { id: 1, name: 'Alice },
 { id: 2, name: 'Bob },
 { id: 1, name: 'Bob },
 { id: 3, name: 'David },
 { id: 2, name: 'David }
]

const source = of(...users);
const example = source.pipe(distinctUntilChanged((ant, act) => ant.name === act.name));

example.subscribe(console.log); // salida: { id: 1, name: 'Alice}, { id: 2, name 'Bob' }, { id: 3, name: 'David' }
Enter fullscreen mode Exit fullscreen mode

En este ejemplo creamos un Observable que emite los objetos de usuario definidos en el array user, luego, aplicamos el operador distinctUntilChanged con una función compare que compara solo los nombres de usuario de dos objetos consecutivos. La salida del Observable resultante es solo los objetos de usuario cuyos nombres son diferentes a los del valor anterior: { id: 1, name: 'Alice}, { id: 2, name 'Bob' }, { id: 3, name: 'David' }

distinctUntilKeyChanged

El operador distinctUntilKeyChanged se utiliza para emitir solo los valores que son diferentes al valor anterior, basándose en una clave especifica de los objetos emitidos. Es similar al operador distinctUntilChanged, pero en lugar de comparar el valor completo emitido, solo compara el valor de una propiedad específica del objeto.

import { of } from 'rxjs';
import { distinctUntilKeyChanged } from 'rxjs/operators';


const users = [
 { id: 1, name: 'Alice },
 { id: 2, name: 'Bob },
 { id: 1, name: 'Bob },
 { id: 3, name: 'David },
 { id: 2, name: 'David }
]

const source = of(...users);
const example = source.pipe(distinctUntilKeyChanged('name');

example.subscribe(console.log); // salida: { id: 1, name: 'Alice}, { id: 2, name 'Bob' }, { id: 3, name: 'David' }
Enter fullscreen mode Exit fullscreen mode

Como puedes ver, solo debemos especificar el key a comparar de los objetos emitido, en este caso el key es name y salida será { id: 1, name: 'Alice}, { id: 2, name 'Bob' }, { id: 3, name: 'David' }

Top comments (0)