Angular 2 – Observables

  • Observables are another way of handling async tasks. Angular2 use them a lot.
  • Usually are objects wrapping some data source which emits events, such as button clicks , https requests, etc.

Captura de pantalla 2017-05-09 a las 17.51.10

Analyzing a Built in observable

  • We already used observables when subscribing to changes int the route params:
    this.route.params.subscribe(
      (params: Params)=> {
        this.id = +params['id'];
        this.editMode = !isNaN(this.id);
      }
    );

Building and using a first simple Observable

  • We will make a observable which print a number in the console every second.
  • This is a built-in utility in rxjs package
...
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';
  ...
ngOnInit() {
    const myNumbers = Observable.interval(1000);
    myNumbers.subscribe(
      (number: number) => {
        console.log(number);
      }
    );
  }

Building and using a custom observable from scratch

  • Let make a custom observable which prints to console after 2 seconds , 4 seconds and complete on five seconds.
    const myObservable = Observable.create((observer: Observer<string>) => {
      setTimeout(()=> {
        observer.next('first package');
      },2000);
      setTimeout(()=> {
        observer.next('second package');
      },4000);
      // setTimeout(()=> {
      //   observer.error('error ocurred!');
      // },5000);
      setTimeout(()=> {
        observer.complete();
      },5000);
      setTimeout(()=> {
        observer.next('third package');
      },6000);
    });

    myObservable.subscribe(
      (data:string)=> { console.log(data); },
      (error:string)=> { console.log(error); },
      ()=> { console.log('completed'); },
    );

NOTE: third package is not printed because it is emitted after observable is completed (dead).

Unsubscribe!

  • We must not forget clean up our subscriptions on leaving the component. Otherwise we could lead to a memory leak. We will do it in the destroy lifecycle method.
...
  subscription1: Subscription;
  subscription2: Subscription;
...
    this.subscription1 = myNumbers.subscribe(
      (number: number) => {
        console.log(number);
      }
    );

    this.subscription2 = myObservable.subscribe(
      (data:string)=> { console.log(data); },
      (error:string)=> { console.log(error); },
      ()=> { console.log('completed'); },
    );
...
  ngOnDestroy() {
    this.subscription1.unsubscribe();
    this.subscription2.unsubscribe();
  }
...

Where to learn more

Using Subject to pass and listen to data

  • Subject is a object from Rxjs package that is Observable and Observer at the same instance.
  • It is very useful in cross component communication instead of emit events

user.service.ts

import {Subject} from 'rxjs/Subject';
...
export class UsersService {
  userActivated = new Subject();
...

app.component.html

      <hr>
      <h4>Using Subjects (from RxJs)</h4>
      <p>
        User is {{userActivated? '(activated)':''}}
        <button (click)="onActivate()">Activate user</button>
      </p>

app.component.ts

...
  userActivated = false;

  constructor(
     private usersService: UsersService ,
...
  ngOnInit() {

    this.subscription3 = this.usersService.userActivated.subscribe(
      (text: string)=> {
        if(text) {
          this.userActivated = true;
        }
    });
...
  onActivate() {
    this.usersService.userActivated.next('dfdfdfd');
  }

Understanding observable operators

  • Observable operators return observables , so you can chain them.
  • In http://reactivex.io/rxjs/ , in the Observable object you can check all operators available.
  • Lets make an example using map operator to print double numbers in the console
    const myNumbers = Observable.interval(1000).map(
      (data:number)=>{
        return data*2;
      }
    );

ds

ds

ds

d

sd