CodeForge

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

Interop signals ↔ observables: toSignal y toObservable

Teoría22 min20 XP

Angular moderno tiene DOS sistemas reactivos: señales (para estado) y Observables (para eventos en el tiempo). No compiten: se complementan, y toSignal/toObservable son el puente entre ellos. Saber cuándo usar cada uno —y cómo conectarlos— es la habilidad que distingue a un desarrollador Angular moderno. Hoy cierras el módulo con la guía definitiva y los dos convertidores.

Dos idiomas, un traductor

toSignal: de Observable a señal

toSignal se suscribe a un Observable y expone su último valor como una señal —gestionando la suscripción y la limpieza por ti—:

tosignal.ts
import { toSignal } from '@angular/core/rxjs-interop';

@Component({ /* ... */ })
export class BuscadorComponent {
private buscador = new FormControl('');

// valueChanges (Observable) → señal reactiva
readonly termino = toSignal(this.buscador.valueChanges, { initialValue: '' });

// ahora 'termino()' es una señal: encaja con computed/effect y el template
readonly esBusquedaValida = computed(() => (this.termino() ?? '').trim().length >= 2);
}

toObservable: de señal a Observable

A veces necesitas lo contrario: tienes una señal (un término de búsqueda en un signal) y quieres aplicarle operadores de RxJS (debounceTime, switchMap). toObservable convierte la señal en un Observable que emite cuando la señal cambia:

toobservable.ts
import { toObservable, toSignal } from '@angular/core/rxjs-interop';

export class BuscadorComponent {
private api = inject(ApiService);
readonly termino = signal('');   // el usuario lo actualiza con termino.set(...)

// señal → Observable, para usar el poder de RxJS en la búsqueda
readonly resultados = toSignal(
  toObservable(this.termino).pipe(
    debounceTime(300),
    distinctUntilChanged(),
    filter((t) => t.trim().length >= 2),
    switchMap((t) => this.api.buscar(t)),
  ),
  { initialValue: [] },
);
}

Este patrón es el mejor de ambos mundos: la ENTRADA es una señal (fácil de actualizar desde el template con termino.set(...)), el PROCESAMIENTO usa RxJS (donde debounceTime+switchMap brillan), y la SALIDA vuelve a ser señal (toSignal) para consumirla en el template. Señal → Observable → señal.

La guía definitiva: ¿señales o RxJS?

Tienes un término de búsqueda en un `signal` y quieres aplicarle `debounceTime` + `switchMap`. ¿Cómo lo conectas?

Mini-reto

Diseña el flujo de un autocompletar de categorías de "Mi Bolsillo": 1) una señal texto que el input actualiza; 2) conviértela a Observable con toObservable y aplícale debounceTime(250), distinctUntilChanged y switchMap a una búsqueda; 3) vuelve el resultado a señal con toSignal (initialValue []). Escribe el esqueleto y marca en qué punto vive cada sistema (señal / RxJS / señal).

Qué sigue

Cierras la teoría de RxJS con la habilidad más valiosa: usar señales y Observables juntos, cada uno en su terreno. El reto del módulo lo corona: vas a construir un BUSCADOR reactivo completo desde cero —con debounce, cancelación de peticiones obsoletas y manejo de errores—, el patrón que resume todo RxJS y que usarás en cualquier app profesional.