material-de-estudos

Operadores do RXJS

Sumário

Piping

Utilizar o método .pipe() dos Observables é útil para combinar operadores de RXJS, sendo executados sequencialmente

Operadores de utilidade

tap - observar side effects

É utilizado para capturar side-effects (efeito colateral) do Observable e monitorar seus valores

Operadores para criar Observables

from - criar observable a partir de uma lista

Utilizado para criar um Observable Através de uma lista iterável (array)

of - criar observable a partir de uma informação

Utilizado para criar um Observable a partir da informação que será passada pra frente

(FUNÇÃO) interval - Emitir números em sequência de um tempo X

(FUNÇÃO) timer - Usado para criar temporizador

Operadores para filtrar informações

filter - filtrar as informações passadas

É usado para filtrar os dados que são passados pelo Observable

Exemplo de utilização do filter para verificar números pares

import { from, tap, filter } from 'rxjs';

numbers$ = from([1, 2, 3, 4, 5, 6, 7, 8]);

ngOnInit(): void {
  this.numbers$
    .pipe(
      // verificar os números pares
      filter((number) => number % 2 == 0),
      tap(console.log)
    )
    .subscribe();
}

map - Transformar os valores emitidos

Usado para transformar os valores emitidos em um observable, e retorna os valores retornados como um novo Observable

Exemplo de utilização do map para transformar cada valor e retornar se é par (even) ou não

import { from, map, tap } from 'rxjs';

numbers$ = from([1, 2, 3, 4, 5, 6, 7, 8]);
ngOnInit(): void {
  this.numbers$
    .pipe(
      map((number) => {
        return number % 2 == 0
          ? { number: number, isEven: true }
          : { number: number, isEven: false };
      }),
      tap(console.log)
    )
    .subscribe();
}
/* OUTPUT:
{number: 1, isEven: false}
{number: 2, isEven: true}
{number: 3, isEven: false}
{number: 4, isEven: true}...
*/

distinctUntilChanged - Obter resultado apenas se for diferente do anterior

Usado para obter o resultado do Observable apenas se não for igual ao resultado anterior

switchMap - Emitir os valores apenas para o Observable mais recente

Trocar (switch) para um novo Observable

debounceTime - Emitir para o Observable apenas se não hover outra chamada de emissão

take - Controlar a quantidade de valores que são emitidos para o Observable

import { take, interval, pipe} from 'rxjs';

// dentro de uma classe
numbersTake$ = interval(1000);

// dentro de um método
takeOperator() {
  const emitter$ = this.numbersTake$.pipe(take(4));

  emitter$.subscribe((val) =>
    console.log(`Emitted from take operator - ${val}`)
  );
}

takeUntil - Emitir valores até outro Observable emitir um valor

import { interval, pipe, takeUntil} from 'rxjs';

// dentro de uma classe
timer$ = timer(6000);
numbersTake$ = interval(1000);

takeUntilOperator() {
  const emitter$ = this.numbersTake$.pipe(takeUntil(this.timer$));

  emitter$.subscribe((val) =>
    console.log(`Emitted from takeUntil operator - ${val}`)
  );
}

Operadores para captura de error

catchError - Capturar erros do Observable

Exemplo de utilização para a captura de um erro

switchMap((query) => {
  return ajax
    .getJSON<any>(`https://api.github.com/users/${query}`)
    .pipe(
      catchError((err) => {
        console.log('Ocorreu uma falha na requisição!');
        return of(err);
      })
    );
})

Exemplo prático

Exemplo de utilização de operadores usando a API do github e o Ajax para requisições. No exemplo é utilizado:

import { debounceTime, distinctUntilChanged, from, map, switchMap, tap, filter, } from 'rxjs';

this.formGithub.controls.username.valueChanges
  .pipe(
    debounceTime(1000),
    filter((string) => string?.trim() != ''),
    tap(console.log),
    distinctUntilChanged(),
    switchMap((query) => {
      return ajax.getJSON<any>(`https://api.github.com/users/${query}`);
    })
  )
  .subscribe((response) => {
    this.user = {
      name: response?.name,
      exists: true,
      avatar_url: response?.avatar_url,
    };
    console.log(response);
  });

O ajax.getJson retorna um Observable, podendo então ser utilizado com o método pipe depois de sua invocação e em seguida ser usado outros operadores do RXJS

//...
  switchMap((query) => {
    return ajax.getJSON<any>(`https://api.github.com/users/${query}`).pipe(
      switchMap(user => ajax.getJSON(user.repos_url))
    );
  })
//...

Operadores de combinações

forkJoin combinar a última emissão de 1 ou mais Observables

import { of, forkJoin } from 'rxjs';

// dentro de uma classe
observable1$ = of('value 1');
observable2$ = of('value 2');
observable3$ = of('value 3');

forkJoinOperator() {
  const result$ = forkJoin([
    this.observable1$,
    this.observable2$,
    this.observable3$,
  ]);
  result$.subscribe((values) => {
    const [firstValue, secondValue, thirdValue] = values;
    console.log(`First Value: ${firstValue}`);
    console.log(`Second Value: ${secondValue}`);
    console.log(`Third Value: ${thirdValue}`);
  });
}