Skip to content

Diferencia Entre Observer y Subscriber

Por Qué se Confunden

Al aprender RxJS, los términos "Observer" y "Subscriber" aparecen y pueden ser confusos. Estos dos están estrechamente relacionados, pero tienen roles claramente diferentes.

¿Qué es un Observer?

Un Observer es una interfaz para recibir datos.

Definición de Observer

typescript
interface Observer<T> {
  next: (value: T) => void;       // Recibir un valor
  error?: (err: any) => void;     // Recibir un error
  complete?: () => void;          // Recibir finalización
}

Rol de Observer

  • Define "cómo" recibir datos
  • Tiene 3 funciones de callback
  • Describe qué hacer

¿Qué es un Subscriber?

Subscriber es una clase que implementa Observer y realiza el proceso de suscripción real.

Rol de Subscriber

  • Ejecuta los callbacks de Observer
  • Mantiene Subscription (gestión de suscripción)
  • Gestiona proceso de cancelación de suscripción
  • Controla cómo ejecutar

Dos Situaciones Donde Aparece Subscriber

Subscriber en realidad aparece en dos situaciones diferentes. Sin embargo, ambos son el mismo objeto Subscriber. Entender esta diferencia es la clave para evitar confusión.

Situación 1: Al Crear un Observable (Recibido como Parámetro)

Al crear un Observable con new Observable(), subscriber se pasa como parámetro a la función constructora.

typescript
import { Observable } from 'rxjs';

// Usar subscriber para publicar valores (el tipo es Subscriber<number>)
const observable$ = new Observable<number>(subscriber => {
  subscriber.next(1);      // Publicar un valor
  subscriber.next(2);
  subscriber.complete();   // Notificar finalización
});

Tipo de subscriber en esta situación

  • Tipo: Subscriber<number>
  • Rol: Usado para publicar datos dentro del Observable
  • Los desarrolladores lo usan directamente (llaman a next(), error(), complete())

Situación 2: Al Llamar a subscribe() (Observer → Convertido a Subscriber)

Cuando llama a subscribe() en un Observable, el Observer pasado por el desarrollador se convierte internamente a un Subscriber.

typescript
// El desarrollador pasa una interfaz Observer
observable$.subscribe({
  next: value => console.log('Siguiente valor:', value),
  error: err => console.error('Error:', err),
  complete: () => console.log('Completo')
});

// ↑ RxJS crea internamente un Subscriber de la siguiente manera
// const subscriber = new Subscriber(observer);
// Y este subscriber se pasa como parámetro en la situación 1

Procesamiento en esta situación

  1. El desarrollador pasa una interfaz Observer
  2. RxJS envuelve internamente el Observer en un Subscriber
  3. Ese Subscriber se pasa a la función constructora del Observable (= subscriber en la situación 1)

Importante: Ambos son el Mismo Objeto Subscriber

El `Subscriber` en las situaciones 1 y 2 es el mismo objeto

typescript
const observable$ = new Observable(subscriber => {
  // Este subscriber es el objeto Subscriber en sí
  // creado cuando se llamó a subscribe()
  subscriber.next(1);
});

observable$.subscribe({
  // Este Observer se envuelve en un Subscriber,
  // y se pasa a la función constructora anterior
  next: v => console.log(v)
});

En otras palabras:

  • El desarrollador llama a subscribe(observer)
  • RxJS crea new Subscriber(observer)
  • Ese Subscriber se convierte en el argumento de la función constructora del Observable
  • Por lo tanto, subscriber en la situación 1 = Subscriber creado en la situación 2

Ilustración de Relaciones

Diferencias Vistas en Código

Ejemplo Completo: Desde la Creación de Observable hasta la Suscripción

typescript
import { Observable } from 'rxjs';

// 1. Al crear Observable: usar subscriber para publicar valores
const observable$ = new Observable<number>(subscriber => {
  console.log('Suscripción iniciada');
  subscriber.next(1);
  subscriber.next(2);
  subscriber.next(3);
  subscriber.complete();
});

// 2. Al suscribirse: pasar Observer (Subscriber se crea internamente)
observable$.subscribe({
  next: value => console.log('Siguiente valor:', value),
  error: err => console.error('Error:', err),
  complete: () => console.log('Completo')
});

// Salida:
// Suscripción iniciada
// Siguiente valor: 1
// Siguiente valor: 2
// Siguiente valor: 3
// Completo

En Este Ejemplo

  • subscriber al momento de creación: Usado para publicar datos dentro del Observable
  • Observer al momento de suscripción: Define el proceso para recibir los datos publicados

Al Pasar un Observer

typescript
import { interval } from 'rxjs';

const observer = {
  next: (value: number) => console.log(value),
  error: (err: any) => console.error(err),
  complete: () => console.log('Completo')
};

// Pasar Observer a subscribe
const subscription = interval(1000).subscribe(observer);
// Internamente, se crea Subscriber y ejecuta los callbacks del observer

Al Pasar Callbacks Directamente (Notación Simplificada)

typescript
// Esto también crea un Subscriber internamente
const subscription = interval(1000).subscribe(
  value => console.log(value),  // next
  err => console.error(err),    // error
  () => console.log('Completo')     // complete
);

Flujo de Operación Real

El siguiente diagrama de secuencia muestra el flujo desde la creación de Observable hasta la suscripción y publicación de datos.

Puntos Importantes de Este Flujo:

  1. Cuando se llama a subscribe(observer), se crea un new Subscriber(observer)
  2. Ese Subscriber se pasa como parámetro a la función constructora del Observable
  3. Cuando se llama a subscriber.next() en la función constructora, se ejecuta el observer.next() interno
  4. En otras palabras, subscriber en la situación 1 = Subscriber creado en la situación 2

Puntos Importantes

Observer es el "plano", Subscriber es el "ejecutor"

  • Observer: Una interfaz que define cómo recibir datos
  • Subscriber: Una clase que implementa el Observer y realmente ejecuta la suscripción
  • Subscriber aparece en dos situaciones

Entender cuándo usar Subscriber

  • Al crear Observable: Use el parámetro subscriber en new Observable(subscriber => {...}) directamente
  • Al suscribirse: Al llamar a subscribe(observer), se crea automáticamente un Subscriber internamente

En ambas situaciones, Subscriber es el mismo objeto con métodos next(), error(), complete().

Patrones de Confusión Comunes

❌ Entendimiento Incorrecto #1

"El subscriber al crear un Observable y el observer al suscribirse son cosas diferentes"

❌ Entendimiento Incorrecto #2

"Subscriber es una implementación interna, por lo que los desarrolladores no lo tocan"

✅ Entendimiento Correcto

Hechos Importantes:

  • El Observer que el desarrollador pasa en subscribe(observer) se envuelve internamente en un Subscriber
  • Ese Subscriber se pasa como parámetro a la función constructora al crear el Observable
  • En otras palabras, subscriber en la situación 1 = Subscriber creado en la situación 2 (mismo objeto)

Entendimiento con Ejemplo Completo

typescript
import { Observable } from 'rxjs';

// 1. Crear Observable (nada se ejecuta en este punto)
const observable$ = new Observable<number>(subscriber => {
  console.log('¡Se ejecutó la función constructora!');
  subscriber.next(1);
  subscriber.next(2);
  subscriber.complete();
});

// 2. Suscribirse (la función constructora se ejecuta por primera vez en este momento)
observable$.subscribe({
  next: v => console.log('Recibido:', v),
  complete: () => console.log('Completo')
});

// Salida:
// ¡Se ejecutó la función constructora!
// Recibido: 1
// Recibido: 2
// Completo

Flujo en Este Ejemplo:

  1. Se llama a observable$.subscribe({...})
  2. RxJS crea new Subscriber({next: ..., complete: ...})
  3. La función constructora (subscriber => {...}) se ejecuta con ese Subscriber como parámetro
  4. Se llama a subscriber.next(1) en la función constructora
  5. Internamente, se ejecuta observer.next(1) y se muestra "Recibido: 1"

En Otras Palabras:

  • subscriber en la situación 1 ← esto
  • Subscriber creado en la situación 2 ← esto
  • ¡Mismo objeto!

Resumen

Comparación de Observer y Subscriber

ObserverSubscriber
TipoInterfazClase (implementa Observer)
RolDefine cómo recibir datosEjecuta proceso de suscripción real
Contenidocallbacks next/error/completeObserver + gestión de Subscription
Cuándo apareceSolo al momento de suscripciónAl crear Observable y al suscribirse

Importante: Relación en Dos Situaciones

SituaciónLo que maneja el desarrolladorTipo realRelación
Al crear ObservableParámetro en new Observable(subscriber => {...})Subscriber<T>El desarrollador lo usa directamente
Al suscribirseObjeto pasado a subscribe(observer)Observer<T> → Convertido internamente a Subscriber<T>RxJS convierte automáticamente

Punto Central

  • El Observer que el desarrollador pasa en subscribe(observer) se envuelve en un Subscriber internamente
  • Ese Subscriber se pasa como parámetro a la función constructora del Observable
  • Por lo tanto, el Subscriber usado en ambas situaciones es el mismo objeto

Próximos Pasos

Ahora que entiende la diferencia entre Observer y Subscriber, aprendamos sobre la gestión de suscripciones real.

Recursos de Referencia

Publicado bajo licencia CC-BY-4.0.