INIZIO blog

Observables jednoduše – co to je a k čemu je to dobré

Zhruba půl roku píšeme nový front-end v Angularu a s ním se staly docela populární Observables. V tomto článku bych se na ně chtěl blíže podívat, případně si ukázat na co se hodí a jak jsme je použili.

Observer a Observable, co to tedy je?

Observables koncept (aka Reactive Streams, aka Reactive Extension) se stává hodně populárním v programování, pokud se dostaneme k asynchronnímu zpracování eventů (Asynchronous data streams). Tento koncept byl vyvinut a zpopularizován Microsoftem. Máme k dispozici mnoho již hotových knihoven (Rx C#, RxJS, RxJava).

Většina zná Observer design pattern, kde základem je generalizované rozhraní pro push notifikace. Observable pak reprezentuje objekt, který posílá notifikace (provider) a Observer pak objekt, který je konzumuje. Jednoduše je Observable stream událostí, které můžeme sledovat nebo poslouchat.

Můžeme si to představit jako osobu, která nám telefonuje (zdroj) a v momentě kdy telefon zvedneme (Subscribe), tak jsme vlastně posluchači její řeči. V ten moment se chováme jako Observer v této řekněme jednosměrné komunikaci. Tato komunikace může být ukončena dvěma způsoby. A to buď osoba na druhém konci ukončí hovor a nebo ho ukončíme my.

Hurá ke kódu

Jak jsem psal, jedná se o stream eventů, pojďme si tedy nějaký vytvořit.

Tímto jsme si vytvořili event stream (Observable) z každého pohybu myši po dokumentu (source). Následně jsme se na tento stream připojili (subscribe) a dané eventy zpracováváme (v našem případě jen vypisujeme souřadnice do konzole).

Na Observable se můžeme dívat jako na pole, které je ale plněno novými hodnotami v čase (a asynchronně). Jakékoliv pole, promise a nebo iterátor může být převeden na Observable za použití konstruktu Observable.from() / Observable.fromPromise(). Tedy například:

Observable.from([1, 2, 3, 4, 5]).subscribe((val) => console.log(val));
> 1
> 2
> 3
> 4
> 5

Operátory

Z principu se pak na jednu Observable můžeme napojit vícekrát a případně použít pro zpracování určité operátory. Operátory jsou metody, které existují na Observables a když je zavoláme, tak nezmění existující instanci, ale vrátí novou (pure) s již aplikovanou logikou.

Pojďme si tedy rozšířit první příklad, na kterém si vše ukážeme. Řekněme například, že chceme všechny eventy pohybu myši, kdy ale součet offsetů pozic je větší než 200. Dále protože víme, že eventů bude hodně, chceme dostat hodnotu vždy jednou za určitý čas (300ms), i když jich nastane v daném intervalu více.

Jak vidíme, na náš stream jsme se napojili vícekrát. Jak je vidět z ukázky první subscription, tak jsme přidali pár zmíněných operátorů, které nám trošku změní celý stream.

  1. pomocí map si přetransformujeme hodnotu na součet obou offsetů
  2. vy-filtrujeme si jen hodnoty, kde tento součet je větší než 200
  3. řekneme, aby se zahodily všechny emitované hodnoty, které se objevily mezi daným časem (debounceTime)

No není to super? Operátorů je celá řada a každý z nich má trochu jiné využití.

Co se týče využití na našem projektu, tak je to například Autocomplete, kde krásně díky debounceTime dostaneme hodnotu inputu zpožděně, abychom neprováděli request po každém znaku.
Navíc díky switchMap jednoduše nahodíme rušení requestů, které aktuálně běží na pozadí a ještě nedoběhly. Nakonec ještě doporučuji projít si článek RxJS – Six Operators That you Must Know (Netanel Basal – anglicky), kde krásně vysvětluje ty nejdůležitější operátory.

Závěrem

Subjektivně se mi práce s Observables hodně líbí, jelikož nám dost zpřehledňuje kód a řeší funkcionality, které by bez nich byly relativně složité (zbytečně komplikovaly kód a vytvářely šum), jako třeba rušení nedoběhlých requestů nebo omezení časem (debounceTime). Prvně jsme s nimi začaly už u staršího projektu, který byl psaný v AngularJS(1.6), a postupem času jsme litovali, že jsme na ně nenarazili dřív.

Související příspěvky:

Autor: 
Lead Dev. #Python #AWS #Angular #Čtvrtkon
  • Ikar Pohorsky

    Bezva clanek! Nebylo by malinko logictejsi u druheho prikladu pouzit nejprve operator debounceTime() a teprve pak pocitat a filtrovat soucet offsetu? Takhle to vypada, ze pocitas „vetsinu“ offsetu zbytecne…

    • twistacz

      Diky za koment. To by pak ale nemuselo splnit zadani, protoze po debouncu dostaneme prave jeden event, a ten by pak nemusel projit podminkou na soucet.

      • Ikar Pohorsky

        Aha! To dava smysl;) Dik

  • Dalibor Jaroš

    dekuji za skvely clanek s praktickou ukazkou. jedna vec vsak nebyla zminena a to je zpetna kompatibilita, lze aplikovat na dnes jiz legendarni Observer (http://wiki.teamliquid.net/starcraft2/Observer_(Legacy_of_the_Void) ? dekuji

    • twistacz

      To je otazka spis na Blizzard 😀