Skip to content

Observable

Observables provide support for passing messages between parts of the application. They are a technique for event handling, asynchronous programming and handling multiple value.

In an Observer pattern, there are two primary entities: 1. Subject 2. Observers. Subject, which is an object, maintains a list of dependents which are known as Observers. Subject notifies all the Observers automatically when there is a state change.

Observables are declarative in nature. An Observer must subscribe to an Observable in order to recieve any values.

An Observable can deliver multiple values such as literals, messages or events depending on the context.

Publish

To create a new Observable, a publisher must instantiate Observable. This instance provides sunscribe() method. Observable instance expects a function as an argument. This function is responsible for generating data that is supposed to be returned the subscribers.

// source: https://angular.io/guide/observables

const locations = new Observable((observer) => {
  let watchId: number;

  // Simple geolocation API check provides values to publish
  if ("geolocation" in navigator) {
    watchId = navigator.geolocation.watchPosition(
      (position: GeolocationPosition) => {
        observer.next(position);
      },
      (error: GeolocationPositionError) => {
        observer.error(error);
      }
    );
  } else {
    observer.error("Geolocation not available");
  }

  // When the consumer unsubscribes, clean up data ready for next subscription.
  return {
    unsubscribe() {
      navigator.geolocation.clearWatch(watchId);
    },
  };
});

// Call subscribe() to start listening for updates.
const locationsSubscription = locations.subscribe({
  next(position) {
    console.log("Current Position: ", position);
  },
  error(msg) {
    console.log("Error Getting Location: ", msg);
  },
});

// Stop listening for location after 10 seconds
setTimeout(() => {
  locationsSubscription.unsubscribe();
}, 10 * 1000);

Definitions

Notification Type Description
next Required. handler for each delivered value. Called zero or more times after execution starts
error Optional. handler for error notification. halts execution of observable instance
complete Optional. hadler for execution-complete notification. delayed values can continue to be delivered to the next handler after execution is complete

Subscribe

Observables would not deliver anything until there's a subscriber. Any code-block/function can subscribe to an Observable instance using the method subscribe(). subscribe() method expects three handlers namely next(), error() and complete(). Out of the three handlers, only the next() is required. There are two ways to pass these arguments. Refer to the following code-block for an illustration.

// of() is a function that creates observable instance. `rxjs` provides this function
const myObservable= of(1, 2, 3);


//>>>>>>>>>> METHOD 1
// observer object
const observers = {
  next(x: number) {
    console.log('next value is', x);
  },

  error(err: Error) {
    console.log(err.message);
  }

  complete() {
    console.log('observable complete');
  }
}

myObservable.subscribe(observers);


//>>>>>>>>>>>> METHOD 2
// subscribe() method can accept callback functions
myObservable.subscribe(
  x => console.log(`next value is ${x}`),
  err => console.log(`error in observable ${err.message}`),
  () => console.log('observable completed')
)

Multicasting

Multicasting is the practice of broadcasting to a list of multiple subscribers in a single execution context. Normally, an Observable creates an independent execution context for each subscribed observers. This behaviour is not always required. Multicasting helps solve this issue.

// TODO: write examples for multicasting