LiveLoveApp logo

Observables are Unicast

Unicast vs Multicast

We need to understand a key distinction between a Subject and an Observable.

By default, an Observable is unicast. This means that each Observer owns a separate execution of the Observable.

On the other hand, a Subject and its subclasses (or variants) are multicast. This means that when a Subject receives a new Observer it does not invoke a new execution for the production of values. Rather, each Observer receives the same produced value(s).

Hot vs. Cold Observable

Before we get into why this matters, we need to first quickly recap the distinction between a hot and a cold Observable:

  • A cold Observable starts to produce values (events, iterators, objects, whatever) upon a new Observer.
  • A hot Observable produces values outside of the Observable, and the Observer begins to receive next notifications of those values until completion or error.

If you are an Angular developer you likely know that the HttpClient is a cold Observable. It is only upon subscribing that the request is sent, and subsequently, the response's next notification is emitted asynchronously containing the response (or body of the response).

Why does this matter?

Most importantly, this matters when the execution of producing values within a cold observable is expensive.

Hypothetically, lets say that the cold observable is making a network request. If I subscribe to the Observable three times then the cold Observable will create three network requests.

Example

Let's look at an example of this:

import { Observable } from "rxjs";

/* create a new observable, providing the observer. */
const observable: Observable<number> = new Observable((observer) => {
  console.log('%cNew subscription created', 'background: #222; color: #bada55');
  let i = 0;

  const interval = setInterval(() => {
    observer.next(i++);
  }, 1000);

  return () => {
    clearInterval(interval);
  };
});

/* Each subscription receives a copy of Observer. */
const subscription = observable.subscribe((value) =>
  console.log('First subscription', value)
);
setTimeout(
  () =>
    subscription.add(
      observable.subscribe((value) => console.log('Second subscription', value))
    ),
  500
);

/* Unsubscribe after 5 seconds. */
setTimeout(() => {
  subscription.unsubscribe();
}, 5000);

See example on codesandbox

When you execute this code you'll notice:

  • The console will log out New subscription created twice. Once for each Observer.
  • We then receive 4 next notifications.
  • Finally, we unsubscribe after 5 seconds.