javascript - Aký je rozdiel medzi Observable a Subject v rxjs?
Prechádzal som tento blog a čítal o Observables a nemohol som prísť na rozdiel medzi Observable a Subject.
Odpoveď č. 1
V programovaní prúdov existujú dve hlavné rozhrania: Observable a Observer.
Observable je pre konzumenta, môže byť transformovaný a prihlásený na odber:
observable.map(x => ...).filter(x => ...).subscribe(x => ...)
Observer je rozhranie, ktoré sa používa na poskytovanie pozorovateľného zdroja:
observer.next(newItem)
Môžeme vytvoriť nový Observable s Observer:
var observable = Observable.create(observer => {
observer.next('first');
observer.next('second');
...
});
observable.map(x => ...).filter(x => ...).subscribe(x => ...)
Alebo môžeme použiť Subject, ktorý implementuje rozhrania Observable aj Observer:
var source = new Subject();
source.map(x => ...).filter(x => ...).subscribe(x => ...)
source.next('first')
source.next('second')
Odpoveď č. 2
Observables sú podľa návrhu unicast a Subjects sú podľa návrhu multicast.
Ak sa pozriete na nižšie uvedený príklad, každé predplatné dostane odlišné hodnoty ako observables vyvinuté ako unicast podľa dizajnu.
import {Observable} from 'rxjs';
let obs = new Observable<any>(observer=>{
observer.next(Math.random());
})
obs.subscribe(res=>{
console.log('subscription a :', res); //subscription a :0.2859800202682865
});
obs.subscribe(res=>{
console.log('subscription b :', res); //subscription b :0.694302021731573
});
Toto môže byť zvláštne, ak očakávate rovnaké hodnoty na oboch predplatných.
Tento problém môžeme prekonať použitím Subjects. Subjects je podobný event-emitteru a nevyvoláva sa pre každý odber. Pozrite si nižšie uvedený príklad.
import {Subject} from 'rxjs';
let obs = new Subject();
obs.subscribe(res=>{
console.log('subscription a :', res); // subscription a : 0.91767565496093
});
obs.subscribe(res=>{
console.log('subscription b :', res);// subscription b : 0.91767565496093
});
obs.next(Math.random());
Obidve predplatné mali rovnakú výstupnú hodnotu!
Odpoveď č. 3
Pozorovateľné
Sú studené: Kód sa vykoná, keď majú aspoň jedného pozorovateľa.
Vytvára kópiu dát: Observable vytvára kópiu dát pre každého pozorovateľa.
Jednosmerné: Pozorovateľ nemôže priradiť hodnotu pozorovateľnému (origin/master).
Kód sa spustí pre každého pozorovateľa. Ak ide o volanie HTTP, zavolá sa pre každého pozorovateľa.
ak je to služba, ktorú chceme zdieľať medzi všetkými komponentmi, nebude mať najnovší výsledok, všetci noví odberatelia sa stále prihlásia na rovnaký observable a získajú hodnotu od začiatku
Unicast znamená, že môže vysielať hodnoty zo zdroja pozorovateľného objektu, nie z inej komponenty.
Predmet
Sú aktívne: kód sa vykonáva a hodnota sa vysiela, aj keď neexistuje žiadny pozorovateľ.
Zdieľané údaje: Rovnaké údaje sa zdieľajú medzi všetkými pozorovateľmi.
obojstranný: Pozorovateľ môže priradiť hodnotu pozorovateľnému (origin/master).
Ak používate subject, potom vám uniknú všetky hodnoty, ktoré sú odvysielané pred vytvorením pozorovateľa. Tu prichádza na scénu Replay Subject.
multicast, môže vysielať hodnoty viacerým odberateľom a môže slúžiť ako odberateľ aj vysielač
Odpoveď č. 4
Našiel som prijatú odpoveď trochu mätúcu!
Pozorovateľ (Observer) nie je rozhraním na poskytovanie dát zdroju (Observable), je to rozhranie na sledovanie (observing) zdroja (Observable)... čo dáva väčší zmysel podľa názvu, však?
Takže dôvod, pre ktorý:
var observable = Observable.create(observer => {
observer.next('first');
observer.next('second');
...
});
funguje - tvorí sa pozorovateľ, ktorý vydá 'first' a potom 'second' - je to tak, že argument pre Observable.create(...) je subscribe funkcia, ktorá v podstate definuje, ktoré Observer udalosti sa vyskytnú priamo na Observer toho Observable.
Ak to chcete rozvinúť ešte trochu ďalej, je dôležité pochopiť, že funkcia subscribe sa pri prihlásení nevolá priamo na objekte Observer, ale je sprostredkovaná objektom Subscription, ktorý dokáže vynucovať správne pravidlá observable, napríklad že Observable nikdy nevydá novú hodnotu po observer.complete() bola vyvolaná, aj keď vaša funkcia odberu vyzerá, že by bola.
REF: http://reactivex.io/rxjs/manual/overview.html#creating-observables
Subjekt (Subject) je zároveň Observovateľný (Observable) aj Observer a opäť vyzerá presne tak, ako keby rozhranie Observer bolo spôsobom, ako „prikŕmiť“ udalosti subjektu (Subject). Ale je ľahšie pochopiť pomenovanie, ak si uvedomíte, že Subject je trochu ako Observable s ekvivalentom funkcie subscribe (t. j. kde definujete, aké udalosti sa stanú pozorujúcim objektom) priamo na objekte, aj po jeho vytvorení. Takže voláte metódy Observer na Subject, aby ste definovali, aké Observer udalosti nastanú na objektoch, ktoré ho pozorujú! 😊 (A opäť, sú zapojené medzikroky, aby sa zabezpečilo, že môžete robiť len legálne sekvencie operácií.)
REF: http://reactivex.io/rxjs/manual/overview.html#subject
Odpoveď č. 5
Pozrite si dokumentáciu rxjs (tam nájdete viac informácií a príkladov): http://reactivex.io/rxjs/manual/overview.html#subject
Čo je Subject? RxJS Subject je špeciálny typ Observable, ktorý umožňuje vysielať hodnoty viacerým Observerom naraz. Kým obyčajné Observables sú unicast (každý prihlásený Observer má nezávislé vykonávanie Observable), Subjects sú multicast.
Predmet (Subject) je ako Pozorovateľ (Observable), ale môže vysielať viacerým Pozorovateľom (Observers). Predmety sú ako Emmitery udalostí (EventEmitters): udržiavajú registráciu mnohých poslucháčov.
a kód, Subject rozširujúci Observable: https://github.com/ReactiveX/rxjs/blob/master/src/internal/Subject.ts#L22
/**
* @class Subject<T>
*/
export class Subject<T> extends Observable<T> implements SubscriptionLike {
//...
}
Odpoveď č. 6
Stručne,
Predmet: Môžete mu posielať a prijímať z neho.
Observable: môžete z neho prijímať iba.
Inými slovami, v subject sa môžete naň prihlásiť a môžete ho použiť na vysielanie ostatným odberateľom kedykoľvek a kdekoľvek v kóde.
zatiaľ čo v observable ho môžete predplatiť iba (nemôžete ho použiť na vysielanie dát po jeho inicializácii). Jediné miesto, odkiaľ môžete vysielať dáta z observable, je v jeho konštruktore.
Odpoveď č. 7
Predstavte si, že do vašej aplikácie prichádza tok dát, ako napríklad v prípade websocketového pripojenia. Chcete spôsob, ako s tým narábať. Existuje niekoľko riešení:
1. bežná ajax požiadavka: Toto riešenie nie je životaschopné, pretože nie je použiteľné na spracovanie push dát. Je to skôr pull než push.
2. Sľub: Tiež nie je dobré, pretože ich musíte spustiť a môžu načítať len raz. Tiež skôr viac ťah než tlač.
Takže aby sme získali tieto údaje, v starých časoch sme používali long-polling. To znamená, že sme nastavili intervalovú funkciu na získavanie tohto prúdu údajov napríklad každú 1 minútu. Hoci to funguje, v skutočnosti to zaťažuje zdroje ako CPU a pamäť.
Ale teraz s možnosťou číslo 3,
3. Observable: Môžete sa prihlásiť a nechať tok dát prichádzať nepretržite, až kým nebude zavolaná funkcia complete.
Super, však? Ale potom je tu ďalší problém. Čo ak chcete niekde vo vašej aplikácii pozorovať prichádzajúce údaje iba raz. Ale chcete tieto údaje zároveň používať po celej aplikácii, keď prídu. Práve vtedy a tam použijete Subject. Umiestnite subject.subscribe() na miesta, kde ich chcete používať v celej aplikácii. Keď údaje prídu, miesta, kde je subject.subscribe(), ich spracujú súčasne. Ale observer sa musí prihlásiť so subject ako jeho argumentom takto.
observer.subscribe(subject).
Príkladom použitia je, keď chcete vytvoriť upozornenie.
Nemôžete mať viacero predplatných toho istého observablu, pretože je pravdepodobné, že každý odberateľ dostane odlišné vstupné dáta. Ale pri subjecte všetci, ktorí sa prihlásia cez subject, budú získavať rovnaké dáta.
Ďalšia analógia je prostredníctvom predplatného časopisu. Každý predplatiteľ dostane časopis so svojím menom. Takže rôzne predplatné=rôzne meno príjemcu. (Normálny Observable) Ale keď ho zdieľate s priateľmi, všetci vaši priatelia dostanú ten istý časopis len s vaším menom. (Normálny Observable s Subject)
Tento muž to vysvetľuje veľmi dobre s príkladom kódu. Môžete si to pozrieť na https://javascript.tutorialhorizon.com/2017/03/23/rxjs-subject-vs-observable/
Dúfam, že táto odpoveď pomôže.
Odpoveď č. 8
Observable môže informovať iba jedného pozorovateľa, zatiaľ čo Subject môže informovať viacerých pozorovateľov.
