Programowanie reaktywne
Observable vs Promise
OBSERVABLE | PROMISE |
---|---|
Umożliwia pracę z wieloma wartościami | Zwraca pojedynczą wartość |
Można go anulować | Nie można go anulować |
Oferuje wiele rozszerzeń dzięki RxJs |
RxJs – wybrane metody
Observable
może reprezentować wiele asynchronicznych strumieni z danymi, do którego to obiektu należy się zasubskrybować subscribe
. Wcześniej jednak RxJs oferuje wiele metod, dzięki którym możemy manipulować strumieniem danych na wiele sposobów. Poniżej lista najciekawszych metod, a następnie przykłady użycia (Observable + metody + subscribe).
- .filter((value:number) => value % 2 === 0 ) – filtruje dane przychodzące zgodnie ze wzorem (w tym wypadku przepuszcza liczby parzyste)
- .delay(500) – opóźnia działanie
- .startWith(0) – rozpoczyna od podanej wartości
- .distinctUntilChanged() – wstrzymuje działanie do momentu, aż nie będzie zmiany
- .timestamp() – dodaje indywidualny znacznik godzinowy
- .last() – przepuści tylko ostatni element
- .first() – tylko pierwszy element
- .find(x => x < 5 ) – tylko pierwszy element, który spełni warunek
- .elementAt(4) – element, którego pozycja została wskazana w nawiasie
- .skip(3) – przeskakuje liczbę wskazanych pozycji począwszy od 1
- .take(2) – pobiera liczbę wskazanych pozycji począwszy od 1
- .max() – wskazuje max pod warunkiem końca strumienia
- .min() – wskazuje min pod warunkiem końca strumienia
- .every(x => x > 0) – typ boolean sprawdza czy wszystkie elementy spełniają warunek dla zakończonego strumienia
- .average(function (x) { return x.value }) – wskazuje średnią wartość, ale typ Observable musi być liczbą
- .toArray() – zwraca wynik jako tablicę
- .debounceTime(2100) – czeka wskazany czas zanim zadziała (pomocne w opóźnianiu zapytań np. oczekiwanie na kilka kliknięć lub na szybkie wpisanie w input)
- .flatMap(x => [x]) – spłaszcza zagnieżdżone observable do jednego płaskiego
- .map(x => x.value + ‚ TS:’ + x.timestamp) – zamienia każdy z obiektów przychodzących przez zastosowanie funkcji (przykład powiązany z .timestamp)
- .map(x => Number(x)+10 ) – drugi łatwiejszy przykład użycia często stosowanej metody .map
Przykłady w Angular2
Przy pierwszym kontakcie z dokumentacją RxJs możemy spotkać się z problemem, ponieważ w dokumentacji wskazany jest następujący sposób na dołączenie tej biblioteki import Rx from 'rxjs/Rx';
. Jeżeli pojawi się błąd: has no default export
, jego rozwiązaniem jest: import * as Rx from 'rxjs/Rx';
Pierwszy przykład:
ngOnInit() {
let counter = 1;
let stream = new Observable(observer => {
setInterval(() => {
observer.next(counter++);
},1000);
setInterval(() => {
observer.complete(); //observer zostaje zakończony po wskazanym czasie
},10100); //w rezultacie otrzymuje 10 liczb od 1 do 10
});
stream
.filter((value:number) => value > 2 )
.map(x => Number(x)+10 )
.subscribe(value => console.log(value));
W wyniku działania otrzymamy w konsoli liczby od 13 do 20 ponieważ wynik jednych metod wpływa na kolejne, które znajdują się poniżej.
Drugi przykład
W pliku nazwa.component.html umieszczamy pole input oraz reakcję na klawisz ENTER:
< input type="text" (keyup.enter)="addArray(temp)" [(ngModel)]="temp">
następnie w pliku nazwa.component.ts właściwy Observable
import { Component, OnInit } from '@angular/core';
import * as Rx from 'rxjs/Rx';
import { Observable } from 'rxjs';
export class NazwaComponent implements OnInit {
constructor() {
}
table = [1, 4, 7, 8, 10];
data;
addArray = function(newData) {
this.table.push(newData);
this.data = Rx.Observable.from(this.table)
.filter((value:number) => value % 2 === 0 )
.delay(500)
.distinctUntilChanged() //wstrzymuje do momentu, aż nie będzie zmiany
.subscribe(x => console.log(x));
}
W rezultacie ze wskazanym opóźnieniem otrzymamy w konsoli liczby parzyste 4, 8, 10 oraz te, które zostały wpisane przez użytkownika i były parzyste.
Trzeci przykład
Najbardziej użyteczny przykład. Na jego bazie możemy robić zapytania typu GET.
import {Http, Response} from '@angular/http';
searchAlbums = function(url) {
this.http.get(url)
.subscribe((response:Response)=>{
let data = response.json()
console.log(data);
})
};
Nie pojawiła się tutaj nazwa Observable tak jak w powyższych przykładach, jednak wystarczy w Visual Code Studio najechać myszą na instrukcję get i zobaczymy, że tutaj również mamy do czynienia z Observable.