Stosowanie Obserwacji

Oto elementarny przykład tworzenia i używania elementu Observable w komponencie Angulara:

import {Component} from '@angular/core';
import {Observable} from 'rxjs/Observable';

@Component({
    selector: 'app-root',
    template: `
      <b>Angular Component Using Observables!</b>

      <h6 style="margin-bottom: 0">VALUES:</h6>
      <div *ngFor="let value of values">- {{ value }}</div>

      <h6 style="margin-bottom: 0">ERRORs:</h6>
      <div>Errors: {{anyErrors}}</div>

      <h6 style="margin-bottom: 0">FINISHED:</h6>
      <div>Finished: {{ finished }}</div>

      <button style="margin-top: 2rem;" (click)="init()">Init</button>
    `
})
export class AppComponent {

  private data: Observable<number>;
  private values: Array<number> = [];
  private anyErrors: boolean;
  private finished: boolean;

  constructor() {
  }

  init() {
      this.data = new Observable(observer => {
          setTimeout(() => {
              observer.next(42);
          }, 1000);

          setTimeout(() => {
              observer.next(43);
          }, 2000);

          setTimeout(() => {
              observer.complete();
          }, 3000);
      });

      let subscription = this.data.subscribe(
          value => this.values.push(value),
          error => this.anyErrors = true,
          () => this.finished = true
      );
  }

}

Zobacz przykład [039]

Najpierw importujemy Observable do naszego komponentu zrxjs/Observable. Następnie tworzymy strumień danych (data) typu number. Czyli strumień danych będzie ciągiem liczb.

W tym strumieniu (obiekt klasy Observable) tworzymy subskrypcję (subscribe), która definiuje reakcję na dane, błędy i zakończenie strumienia z powodzeniem.

Zamiast subscribe możemy użyć forEach do nasłuchiwania danych. Kluczową różnicą między forEach isubscribe jest sposób obsługi wywołań zwrotnych błędu i zakończenia. Wywołanie forEach działa na obietnicach (promises). Kiedy Observable się kończy, obietnica zostaje rozwiązana. Kiedy Observable napotka błąd, obietnica zostaje odrzucona.

Możesz myśleć o Observable.of(1, 2, 3).forEach(doSomething) jako semantycznie równoważnym:

new Promise((resolve, reject) => {
  Observable.of(1, 2, 3).subscribe(
    doSomething,
    reject,
    resolve);
});

Wzorzec forEach jest przydatny w przypadku sekwencji zdarzeń, które można spodziewać się tylko raz.

export class AppComponent {

  private data: Observable<number>;
  private values: Array<number> = [];
  private status = "";

  constructor() {
  }

  init() {
      this.data = new Observable(observer => {
          setTimeout(() => {
              observer.next(42);
          }, 1000);

          setTimeout(() => {
              observer.next(43);
          }, 2000);

          setTimeout(() => {
              observer.complete();
          }, 3000);

          this.status = "Started";
      });
      let subscription = this.data.forEach(v => this.values.push(v))
      .then(() => this.status = "Ended");
  }

}

Zobacz przykład [040]