19 martie 2020

Angular - ziua 5 - Observables

Observable - o sursa de date; declansat de un eveniment creat de utilizator; declansat de Http requests; poate fi declansat programatic;
--------
-- Observable --> .... stream .... -> Observer
--------
Observer-ul poate sa prelucreze datele, erorile, sau sa coordoneze terminarea, in fiecare dintre aceste actiuni se poate scrie cod (asincron) care sa fie executat.

Exemple: la un route: ActivatedRoute => route.params este un Observable, este un stream de parametri care ofera un nou parametru de fiecare data cand se schimba URL-ul
- la observabile poti doar sa faci subscribe(...)
- rolul lor cel mai important este sa emita date

Construirea unui observabil de la 0

import { interval } from 'rxjs';

// intr-o clasa:
ngOnInit() {
    interval(1000).subscribe(count => { console.log(count); } ); // primim un eveniment in fiecare secunda
}

!!! Trebuie facut unsubscribe daca observabilul nu mai este de interes (salvare Subscription intr-o variabila, si apelarea unsubscribe() in onDestroy()). Altfel, la reinitializarea componentei, se va adauga de fiecare data un nou observabil pe langa cele deja existente.
!!! Exceptie de la aceasta regula fac toti observabilii furnizati de Angular (cum ar fi route.params si altii) pentru care nu trebuie sa se apeleze unsubscribe().

Construire cu adevarat de la 0:

import { Observable } from 'rxjs';

ngOnInit() {
    const customIntervalObservable = Observable.create(observer => { 
        let count = 0;
        setInterval(() => { observer.next(count); count++; }, 1000) ;
    });

    // folosire:
    customIntervalObservable.subscribe(data => { console.log(data); });
}

// 1000 este timeout-ul
// observer.next() emite o noua valoare; se poate folosi alternativ observer.error() sau observer.complete()

Tratarea erorilor -> observer.error(new Error(' etc '));
- observabilul moare dupa ce emite o eroare (nu mai e nevoie de unsubscribe), totusi nu e acelasi lucru cu terminarea
- prindere: customIntervalObservable.subscribe(data => { console.log(data); , error => { console.error("Caught it"); } );

Terminarea unui observabil -> observer.complete();
- prindere: customIntervalObservable.subscribe(data => { console.log(data); , error => { console.error("Caught it"); }, () -> { console.log('do some cleanup'); } );
- nu este nevoie de unsubscribe()

Operatori - ajuta la construirea unor pasi prin care vrei sa obtii datele
- exemple: map, filter, expand, etc.

import { map } from 'rxjs/operators';

// in ngOnInit()
customIntervalObservable.pipe( map((data: number) => { return 'Round ' + (data + 1); }) ).subscribe(....);

customIntervalObservable.pipe( filter(...), map(...) ).subscribe(....);

Subiecti - un fel de Observable, dar sunt mai activi pentru ca se poate chema metoda next() pe ei din exterior (pe cand in observabile, next() se poate apela doar din interior)
- fiind tot niste observabile, se poate apela in continuare subscribe() si, de asemenea, unsubscribe()
- se recomanda folosirea subiectilor in detrimentul EventEmitter-ilor (mai putin cand obiectul este si un Output())
- subiectii sunt pentru comunicarea intre componente prin servicii, prin mecanisme la care se face subscribe() manual.

// in user.service.ts
import { Subject } from 'rxjs';

activatedEmitter = new Subject<boolean>(); // putea fi EventEmitter<boolean>

// Html:
<button (click)="onActivated()" />

// Ts:
onActivate() {
    this.userService.activatedEmitter.next(true); // era emit(true) pt EventEmitter
}

---
Sursa: Udemy, section 13+14

Niciun comentariu: