Kiedy używać asObservable () w rxjs?


88

Zastanawiam się, jaki jest pożytek z asObservable:

Zgodnie z dokumentami:

Obserwowalna sekwencja, która ukrywa tożsamość sekwencji źródłowej.

Ale dlaczego miałbyś ukrywać sekwencję?

Odpowiedzi:


189

Kiedy używać Subject.prototype.asObservable ()

Ma to na celu zapobieżenie wyciekowi „strony obserwatora” podmiotu z API. Zasadniczo, aby zapobiec nieszczelnej abstrakcji, gdy nie chcesz, aby ludzie byli w stanie „przejść” do wynikowego obserwowalnego.

Przykład

(UWAGA: To naprawdę nie jest sposób, w jaki powinieneś przekształcić źródło danych w Observable, zamiast tego powinieneś użyć new Observablekonstruktora, patrz poniżej).

const myAPI = {
  getData: () => {
    const subject = new Subject();
    const source = new SomeWeirdDataSource();
    source.onMessage = (data) => subject.next({ type: 'message', data });
    source.onOtherMessage = (data) => subject.next({ type: 'othermessage', data });
    return subject.asObservable();
  }
};

Teraz, gdy ktoś uzyska obserwowalny wynik, myAPI.getData()nie może nextwartościować wyniku:

const result = myAPI.getData();
result.next('LOL hax!'); // throws an error because `next` doesn't exist

new Observable()Jednak zwykle powinieneś używać

W powyższym przykładzie prawdopodobnie tworzymy coś, czego nie chcieliśmy. Po pierwsze, getData()nie jest leniwy jak większość obserwabli, natychmiast utworzy bazowe źródło danych SomeWeirdDataSource(i prawdopodobnie niektóre efekty uboczne). Oznacza to również, że jeśli ty retrylub repeatwynikowy obserwowalny, nie będzie działać tak, jak myślisz, że będzie.

Lepiej jest zawrzeć tworzenie źródła danych w obserwowalnym, jak poniżej:

const myAPI = {
  getData: () => return new Observable(subscriber => {
    const source = new SomeWeirdDataSource();
    source.onMessage = (data) => subscriber.next({ type: 'message', data });
    source.onOtherMessage = (data) => subscriber.next({ type: 'othermessage', data });
    return () => {
      // Even better, now we can tear down the data source for cancellation!
      source.destroy();
    };
  });
}

Z powyższym kodem, każde zachowanie, w tym uczynienie go „nie leniwym”, można skomponować na wierzchu obserwowalnego przy użyciu istniejących operatorów RxJS.


3
TX Ben ... śledził twoje rzeczy ... tx dla całego wspaniałego wsparcia na RX
born2net

3
@Shardul ... zasubskrybowałbyś wynik:result.subscribe(value => doSomething(value))
Ben Lesh

2
@BenTaliadoros Tak, za każdym razem return subject.asObservable();będzie to nowe obserwowalne. Będziesz mieć jedną zmienną składową Subject, a onMessage / onOtherMessage zostanie zadeklarowany w warunku lub podczas inicjalizacji (nie przy każdym wywołaniu). Użyłem tego podejścia, pipe( filter() )opierając się na parametrze dostarczonym do getData()funkcji. The
Drenai

5
@BenLesh, w drugiej próbce kodu subjectma być subscriber?
Florin D

1
Chciałbym również tutaj sprawdzić: czy subject.nextlinie powinny być subscriber. Ponadto „jeśli spróbujesz ponownie lub powtórzysz wynikową obserwację, nie będzie działać tak, jak myślisz”. Czy mógłbyś to sprecyzować? Czy masz po prostu na myśli, że new SomeWeirdDataSource()będzie się to działo za każdym razem, gdy getDatazostanie wywołany, i że przez zawijanie go new Observablesprawisz, że instancja będzie czekać na subskrypcję. Chyba nie widzę, kiedy sprawdzisz getDatabez znaku, .subscribewięc brakuje mi wartości. Wreszcie, co według Ciebie stanie się, aby „zniszczyć źródło danych”? Dzięki.
1252748

7

A Subjectmoże działać zarówno jako plik, jak observeri jako observable.

Na Obervable ma 2 metody.

  • Subskrybuj
  • wypisz się

Kiedykolwiek subskrybować do observable, masz observerktóry ma kolejną , błąd i kompletne metody.

Musisz ukryć sekwencję, ponieważ nie chcesz, aby źródło strumienia było publicznie dostępne w każdym komponencie. Możesz się odwołać@BenLesh przykładu.

PS: Kiedy pierwszy raz przeszedłem przez Reactive Javascript, nie byłem w stanie tego zrozumieć asObservable. Ponieważ musiałem się upewnić, że dobrze rozumiem podstawy, a następnie zacząłem asObservable. :)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.