When developing an Angular application one frequently encounters the need to communicate and share data between different components. Now, there are different ways of doing this, and a common one is the use of Subjects and Subscriptions, and the very base of that lay the RxJS Observables.

RxJS Observables may seem a very vast and complex subject, but in this guide we will focus in the basics we need to understand to be able to use them effectively in our Angular applications.

What are Observables, observers, and subscriptions

Before we get started a bit of vocabulary is in order:

  • Observable: an item who emits a stream of events
  • Observer: an item who listens to the Observable

An observer subscribes to an observable in order to receive and react to the events emitted by the observable.

It pretty much works like the old newspapers subscriptions: the newspaper company would be the observable who periodically emits the weekly newspaper, the subscriber who receives every week the newspaper in his home is the observer. And in order for this process to take place the customer has to subscribe to the newspaper: for as long as he is subscribed the newspapers would show regularly at his doorstep. Also ,as in real life, subscriptions can be cancelled.

Using Observables: an example

Let’s apply the concepts we are talking about in a very simple example:

import { Component, OnInit, OnDestroy } from "@angular/core";
import { from, Observable, Subscription, PartialObserver } from "rxjs";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent implements OnInit, OnDestroy{
  private _mySubscription: Subscription;

  public ngOnInit() {
    let observable: Observable = from([1, 2, 3, 7, 8, 9]);

    const myObserver:PartialObserver = {
      next: x => console.log(`Observer next value: ${x}`),
      error: err => console.error(`Observer error value: ${err}`),
      complete: () => console.log(`Observer complete notification`)
    };

    this._mySubscription = observable.subscribe(myObserver);
  }

  public ngOnDestroy() {
    this._mySubscription.unsubscribe();
  }
}

In the example above we have started by creating an Observable:

let observable: Observable = from([1, 2, 3, 7, 8, 9]);

There are various ways to create an observable: in the example above we use the function from that allows to create an observable from an iterable object. In our example the observable object will emit the numbers  1, 2, 3, 7, 8, 9 and then will be completed.

Next we have created an Observer for our Observable :

    const myObserver:PartialObserver = {
      next: x => console.log(`Observer next value: ${x}`),
      error: err => console.error(`Observer error value: ${err}`),
      complete: () => console.log(`Observer complete notification`)
    };

In the observer we have implemented 3 callbacks:

  • next: reacts to each emitted event
  • error: an error has ocurred
  • complete: we have finished emitting all our events

We do not need to provide and implementation for the three methods, if we do not want to respond in any particular way to error, or if we do not care that we have reached the end of the event stream, we can simply provide an implementation for the next method:

    const myObserver:PartialObserver = {
      next: x => console.log(`Observer next value: ${x}`)
    };

Lastly we have subscribed our observer to the event emitter (the observable):

  this._mySubscription = observable.subscribe(myObserver);

The subscribe method subscribes the observer to the observable so that the observer starts receiving the events emitted by the observable. Moreover the subscribe method returns a subscription object that we can use to cancel the subscription.

We are disposing the subscription in the destroy method of the component:

  public ngOnDestroy() {
    this._mySubscription.unsubscribe();
  }

An equivalent, but more commonly encountered implementation of our example would be this one:

import { Component, OnInit, OnDestroy } from "@angular/core";
import { from, Observable, Subscription, PartialObserver } from "rxjs";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy{
  private _mySubscription: Subscription;

  public ngOnInit() {
    let observable: Observable = from([1, 2, 3, 7, 8, 9,10]);

    this._mySubscription = observable.subscribe((x) => {
        console.log(`Observer next value: ${x}`);
      },
      (err) => console.error(`Observer error value: ${err}`),
      () => console.log(`Observer complete notification`)
     );
  }

  public ngOnDestroy() {
    this._mySubscription.unsubscribe();
  }
}

Before we finish I would like direct your attention to the way we created the observable in the previous sample code:

let observable: Observable = from([1, 2, 3, 7, 8, 9,10]);

If an observable is going to emit events that an observer is going to receive, we need a source of data to emit, and in our sample we used the from function to convert a run of the mill array in an observable. Although that made for a quick, and easy to understand observable, in real life we have a wide array of possibilities to create an observable: you can check them at the Angular site on observables.

That’s all for today, thanks for reading.