RxJS: 2. Operadores II

Operadores de RxJS (segunda parte)

archivado en: JavaScript / 9 abril, 2018 / taller:

En la entrada anterior de esta serie dedicada a RxJS vimos qué eran los operadores y cómo se clasificaban en varios grupos según su naturaleza: para crear observables, matemáticos, filtros, y condicionales. En esta entrada seguimos con los grupos que faltaban por explicar.

E. De transformación

Este grupo reúne operadores que sirven para transformar la respuesta del observable antes de que lleguen al observer y hay un montón.

  • buffer
  • bufferCount
  • bufferTime
  • bufferToggle
  • bufferWhen
  • concatMap
  • concatMapTo
  • exhaustMap
  • expand
  • groupBy
  • map
  • mapTo
  • mergeMap
  • mergeMapTo
  • mergeScan
  • pairwise
  • partition
  • pluck
  • scan
  • switchMap
  • switchMapTo
  • window
  • windowCount
  • windowTime
  • windowToggle
  • windowWhen

Veamos algunos a modo de ejemplo.

1. map. Equivale al método map() de javaScript y sirve para hacer algo con cada uno de los valores de la colección, como multiplicarlos por dos en este ejemplo.

let myArray = [1, 2, 3];

Rx.Observable

.from(myArray)

.map(value => 2 * value)

.subscribe(value => console.log(value));

// 2

// 4

// 6

2. pluck. Este operador sirve para seleccionar solo una propiedad de un objeto o array de objetos.

let myObject = [{foo: 'a', bar: 'b'}, {foo: 'c', bar: 'd'}];

Rx.Observable

.from(myObject)

.pluck('foo')

.subscribe(value => console.log(value));

// a

// c

3. scan. A partir de un valor semilla opcional (10 en el ejemplo), aplica un valor que se va acumulando en cada ítem de la colección.

let myArray = [1, 2, 3];

Rx.Observable

.from(myArray)

.scan((acc, current) => acc + current, 10)

.subscribe(value => console.log(value));

// 11

// 13

// 16

4. groupBy. Como indica su nombre, este operador permite agrupar los items de una colección por un valor que se repita en alguna de las propiedades.

myObject = [

{foo: 'a', bar: 1},

{foo: 'a', bar: 2},

{foo: 'b', bar: 3},

{foo: 'b', bar: 4},

{foo: 'c', bar: 5}

];

Rx.Observable

.from(myObject)

.groupBy((item)=> item.foo)

.subscribe(value => console.log(value));

// {_isScalar: false, key: "a" ...

// {_isScalar: false, key: "b" ...

// {_isScalar: false, key: "c" ...

5. switchMap. Este operador se utiliza mucho y sirve concatenar observables en una serie de la que solo se emite el último. Por ejemplo, imaginemos que necesitamos los resultados de una llamada ajax para lanzar una segunda, que es la que luego usaremos para pintar una vista (en el ejemplo uso los endpoints que amablemente se exponen en https://restcountries.eu).

const getCountry = Rx.Observable.ajax('https://restcountries.eu/rest/v2/name/eesti');

const finalHttp = getCountry.switchMap(sourceValue => {

// estonia

console.log(sourceValue);

return Rx.Observable.ajax('https://restcountries.eu/rest/v2/name/spain');

});

finalHttp.subscribe(

(value)=> {

// spain

console.log(value);

},

(error) => console.error(error),

()=> console.log('Complete')

);

// los datos de spain

6. buffer. Este operador es algo complejo. Permite ir almacenando los resultados de una fuente observable y los emite en un array cuando se solicitan desde otro observable. Por ejemplo, en este caso tenemos un observable en un evento click. Si no estuviera buffereado, al clickar en la pantalla, emitiría un valor; pero lo interceptamos con un buffer que parte de un observable interval que acumula las respuesta cada segundo.

let clicks = Rx.Observable.fromEvent(document, 'click');

let interval = Rx.Observable.interval(1000);

let buffered = interval.buffer(clicks);

buffered.subscribe(x => console.log(x));

F. Utilidades

Es un grupo heterogéneo de operadores que igual podían haber llamado también cajón de sastre y que se caracterizan por aportar alguna utilidad. Son:

  • do
  • delay
  • delayWhen
  • dematerialize
  • finally
  • let
  • materialize
  • observeOn
  • subscribeOn
  • timeInterval
  • timestamp
  • timeout
  • timeoutWith
  • toArray
  • toPromise

Veamos algunos.

1. delay. Retrasa la emisión de los datos el tiempo indicado en milisegundos en el operador.

let myArray = [1, 2, 3, 9];

Rx.Observable

.from(myArray)

.delay(1000)

.subscribe(value => console.log(value));

2. do. Se utiliza para debuguear y permite hacer algo con los valores antes de la colección antes de emitirlos sin que se vean afectados.

Rx.Observable

.from(myArray)

.do(value => console.log(`do ${value}`))

.subscribe(value => console.log(value));

/*

do 1

1

do 22

do 3

3

do 9

9

*/

3. materialize. Añade información a los datos que se están emitiendo en cada next, el error y el complete.

Rx.Observable

.from(myArray)

.materialize()

.subscribe(value => console.log(value));

// {kind: "N", value: 1, error: undefined, hasValue: true}

// {kind: "N", value: 2, error: undefined, hasValue: true}

// ..

4. timeout. Lanza un error si no se ha emitido ningún dato en plazo fijado en milisegundos.

Rx.Observable

.of('foo')

.delay(200)

.timeout(100)

.subscribe(

value => console.log(value),

error => console.log(error)

);

// {name: "TimeoutError", stack: "TimeoutError: Timeout has occurred

5. timestamp. Añade el timestamp en cada dato emitido.

Rx.Observable

.from(myArray)

.timestamp()

.subscribe(value => console.log(value));

// {value: 1, timestamp: 1514551928846}

// {value: 2, timestamp: 1514551928846}

6. toArray. Agrupa los valores en un array.

Rx.Observable

.of(1, 2, 3)

.toArray()

.subscribe(arr => console.log(arr));

// [1, 2, 3]

7. toPromise. Devuelve los valores en una promesa.

let myPromise = Rx.Observable

.of('bar')

.toPromise();

myPromise.then((value)=> console.log(value));

// bar

G. Error

Este conjunto de operadores igual se podía haber agrupado con el anterior. Son solo tres y sirven para gestionar errores.

  • catch
  • retry
  • retryWhen

1. catch. Es el operador más interesante de este grupo y equivaldría al try cacht de javaScript. Captura un error que se puede devolver como observable.

Rx.Observable

.throw('Houston, Houston...')

.catch(val => Rx.Observable.of(`${val} we have a problem`))

.subscribe(value => console.log(value));

// Houston, Houston... we have a problem

H. De combinación.

Estos operadores sirven para combinar observables.

  • combineAll
  • combineLatest
  • concat
  • concatAll
  • exhaust
  • forkJoin
  • merge
  • mergeAll
  • race
  • startWith
  • switch
  • withLatestFrom
  • zip
  • zipAll

1. combineLatest. Enlaza el último valor emitido de un observable con los valores de otro, directamente o pasando por un método intermedio.

let myArray = [1, 3, 5];

let myObservable = Rx.Observable

.from(myArray);

let mySecondArray = [2, 4];

let mySecondObservable = Rx.Observable

.from(mySecondArray);

Rx.Observable

.combineLatest(myObservable, mySecondArray)

.subscribe(value => console.log(value));

// [5, 2]

// [5, 4]

Rx.Observable

.combineLatest(myObservable, mySecondObservable, (f, s)=> f * s)

.subscribe(value => console.log(value));

// 10

// 20

2. concat. Concatena dos o más observables.

myObservable

.concat(mySecondObservable)

.subscribe(value => console.log(value));

// 1

// 3

// 5

// 2

// 4

3.  forkJoin. Es similar al q.all del sistema de promises de kriskowal (el que se usaba en Angular 1.*); lanza observables en paralelo y las agrupa en un observable que se dispara cuando han concluido todos.

let first = Rx.Observable.of({source:1,value:'a'});

let second =Rx.Observable.of({source:2,value:'b'});

Rx.Observable.forkJoin(first, second)

.subscribe(value => console.log(value));

// {source: 1, value: "a"}

// {source: 2, value: "b"}

4. startWith. Concatena la secuencia de valores de un observable antes de la secuencia de otro observable.

myObservable = Rx.Observable

.of('beautiful day')

.startWith('its a')

.subscribe(value => console.log(value));

// its a

// beautiful day

|| Tags: , ,

Este artículo aún no ha sido valorado.

¿Te ha parecido útil o interesante esta entrada?
dormido, valoración 1 nadapensativo, valoración 2 un poco sonrisa, valoración 3 a medias guiño, valoración 4 bastante aplauso, valoración 5 mucho

Tú opinión es muy importante, gracias por compartirla!

Los comentarios están cerrados.