CodeForge

Angular 21 de Cero a Experto / RxJS y observables a gran escala

Operadores y pipe: transformar el stream

Teoría24 min20 XP

Un Observable en crudo rara vez es lo que quieres: quieres mapear sus valores, filtrar los que no sirven, o esperar a que el usuario deje de escribir antes de reaccionar. Los OPERADORES son funciones que transforman un stream en otro, y pipe los encadena como una tubería. Hoy dominas los operadores esenciales —map, filter, tap, debounceTime— y entiendes por qué pipe se lee como una línea de montaje.

La línea de montaje

pipe: encadenar operadores

pipe recibe operadores y los aplica en orden, devolviendo un Observable nuevo:

pipe.ts
import { of, map, filter } from 'rxjs';

of(1, 2, 3, 4, 5).pipe(
filter((n) => n % 2 === 0),   // deja pasar solo los pares: 2, 4
map((n) => n * 10),           // los multiplica: 20, 40
).subscribe((v) => console.log(v));   // imprime 20, luego 40

El orden importa: filter antes que map filtra los originales; al revés, mapearía todos y filtraría los resultados. Cada operador recibe el stream de arriba y produce uno nuevo —nunca muta el original—.

Los operadores esenciales

El caso estrella: una búsqueda en vivo

Este pipeline es el "hola mundo" de RxJS —y demuestra por qué existe—:

busqueda.ts
import { debounceTime, distinctUntilChanged, filter, map } from 'rxjs';

// this.buscador es un FormControl; valueChanges es su Observable
this.buscador.valueChanges.pipe(
map((texto) => (texto ?? '').trim()),   // limpia
filter((texto) => texto.length >= 2),   // ignora búsquedas muy cortas
debounceTime(300),                       // espera a que el usuario pare de teclear
distinctUntilChanged(),                  // ignora si el término no cambió
).subscribe((termino) => this.buscar(termino));

Sin RxJS, esto serían varios setTimeout, banderas y comparaciones a mano. Con operadores, es una tubería declarativa que se lee como una frase: "limpia, ignora lo corto, espera 300ms tras la última tecla, ignora repeticiones, y busca". El debounceTime solo evita decenas de peticiones inútiles mientras el usuario escribe.

Pruébalo: tu propio map y filter en un stream

Los operadores son funciones que envuelven un Observable y devuelven otro. Aquí, un mini-RxJS con map y filter sobre tu Observable, en vivo:

Observa cómo cada operador (map, filter) toma la fuente y devuelve un Observable NUEVO que, al recibir un valor, lo transforma o filtra antes de reenviarlo. pipe solo los encadena con un reduce. Es exactamente el mecanismo de RxJS: operadores puros que se componen, sin mutar el stream original. La misma composición de funciones del SC-02, sobre valores en el tiempo.

¿Para qué sirve `debounceTime(300)` en una búsqueda en vivo?

Mini-reto

En el playground, añade dos operadores a tu mini-RxJS: 1) tap(fn) que ejecute un efecto (un console.log) sin alterar el valor y lo reenvíe; 2) take(n) que emita solo las primeras n emisiones y complete. Encadénalos en un pipe con map y filter, y verifica el orden de ejecución. Piensa qué cambia si pones tap antes o después del map.

Qué sigue

Ya transformas un stream de valores simples. Pero ¿qué pasa cuando cada valor del stream dispara OTRO Observable —un término de búsqueda que dispara una petición HTTP—? Eso es un "higher-order observable", y su manejo (con switchMap) es una de las partes más importantes —y sutiles— de RxJS. La próxima lección.