São funções puras que transformam, filtram ou combinam streams de dados de em Observables.

O .pipe() é usado para encadear operadores, tipo uma composição.

todosPedidos$ = this.pedidoService.getPedidos();
 
totalPendentes$ = this.todosPedidos$.pipe(
  map(pedidos => pedidos.filter(p => p.status === 'PENDENTE')),
  map(pendentes => pendentes.length)
);

Operadores de Transformação

map

Transforma cada valor emitido aplicando uma função.

nomes$ = this.usuarios$.pipe(
  map(users => users.map(u => u.nome))
);
 
produtosComDesconto$ = this.produtos$.pipe(
  map(produtos => produtos.map(p => ({
    ...p,
    preco: p.preco * 0.9
  })))
);

switchMap

Cancela a requisição anterior e faz uma nova. Usado em buscas e navegação.

// Busca que cancela requisições anteriores (para digitação)
resultados$ = this.buscaControl.valueChanges.pipe(
  debounceTime(300),
  distinctUntilChanged(),
  switchMap(termo => this.searchService.buscar(termo))
);
 
detalhes$ = this.idSelecionado$.pipe(
  switchMap(id => this.api.getDetalhes(id))
);

mergeMap (ou flatMap)

Executa múltiplas requisições em paralelo sem cancelar as anteriores.

uploadArquivos(arquivos: File[]) {
  return from(arquivos).pipe(
    mergeMap(arquivo => this.uploadService.upload(arquivo)),
    toArray()
  );
}

concatMap

Executa requisições em sequência, aguardando a anterior terminar.

processarPedidos(pedidos: Pedido[]) {
  return from(pedidos).pipe(
    concatMap(pedido => this.api.processar(pedido))
  );
}

Operadores de Filtragem

filter

usuariosAtivos$ = this.usuarios$.pipe(
  filter(users => users.filter(u => u.ativo))
);
 
valoresAltos$ = this.numeros$.pipe(
  filter(n => n > 100)
);

distinctUntilChanged

Emite apenas quando o valor muda em relação ao anterior.

// Evita requisições duplicadas em inputs (digitação)
busca$ = this.searchControl.valueChanges.pipe(
  distinctUntilChanged(),
  switchMap(termo => this.api.buscar(termo))
);

debounceTime

buscaOtimizada$ = this.searchControl.valueChanges.pipe(
  debounceTime(300),
  distinctUntilChanged(),
  switchMap(termo => this.api.buscar(termo))
);

take / takeUntil

Limita a quantidade de emissões ou cancela baseado em outro Observable.

primeiros$ = this.stream$.pipe(take(5));
 
// Cancela quando componente é destruído
export class MeuComponent implements OnDestroy {
  private destroy$ = new Subject<void>();
  
  dados$ = this.api.getDados().pipe(
    takeUntil(this.destroy$)
  );
  
  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }
}

Operadores de Combinação

combineLatest

Combina múltiplos Observables (usa sempre o último valor de cada um), emitindo sempre que qualquer um emite.

// Filtro combinado
produtosFiltrados$ = combineLatest([
  this.categoriaControl.valueChanges,
  this.precoControl.valueChanges,
  this.produtos$
]).pipe(
  map(([categoria, precoMax, produtos]) => 
    produtos.filter(p => 
      p.categoria === categoria && p.preco <= precoMax
    )
  )
);

Operadores Utilitários

tap

Executa efeitos colaterais sem modificar o stream.

dados$ = this.api.getDados().pipe(
  tap(dados => console.log('Dados recebidos:', dados)),
  tap(dados => this.loading = false),
  map(dados => this.transformar(dados))
);

catchError

usuarios$ = this.api.getUsuarios().pipe(
  catchError(error => {
    console.error('Erro ao buscar usuários:', error);
    this.notificacao.erro('Falha ao carregar dados');
    return of([]);
  })
);
 
dadosComRetry$ = this.api.getDados().pipe(
  retry(3),  // Tenta 3 vezes antes do catch
  catchError(error => of(null))
);