Wann soll asObservable () in rxjs verwendet werden?

84

Ich frage mich, wozu es gut ist asObservable:

Gemäß Dokumentation:

Eine beobachtbare Sequenz, die die Identität der Quellsequenz verbirgt.

Aber warum sollten Sie die Sequenz ausblenden müssen?

born2net
quelle

Antworten:

187

Wann sollte Subject.prototype.asObservable () verwendet werden?

Damit soll verhindert werden, dass die "Beobachterseite" des Subjekts aus einer API austritt. Grundsätzlich, um eine undichte Abstraktion zu verhindern, wenn Sie nicht möchten, dass Menschen in der Lage sind, in das resultierende Beobachtbare "weiter" zu gelangen.

Beispiel

(HINWEIS: Auf diese Weise sollten Sie eine solche Datenquelle nicht zu einem Observable machen, sondern den new ObservableKonstruktor verwenden (siehe unten).

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();
  }
};

Wenn jemand das beobachtbare Ergebnis erhält, kann er das Ergebnis myAPI.getData()nicht nextbewerten:

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

Sie sollten in der Regel verwenden new Observable(), obwohl

Im obigen Beispiel erstellen wir wahrscheinlich etwas, das wir nicht wollten. Zum einen getData()ist es nicht faul wie die meisten Observablen, es wird SomeWeirdDataSourcesofort die zugrunde liegende Datenquelle (und vermutlich einige Nebenwirkungen) erstellen . Dies bedeutet auch, dass wenn Sie retryoder repeatdas resultierende beobachtbare Objekt nicht so funktionieren, wie Sie es sich vorstellen.

Es ist besser, die Erstellung Ihrer Datenquelle in Ihrem Observable wie folgt zu kapseln:

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();
    };
  });
}

Mit dem obigen Code kann jedes Verhalten, einschließlich der Tatsache, dass es "nicht faul" ist, mithilfe der vorhandenen Operatoren von RxJS über dem Observable erstellt werden.

Ben Lesh
quelle
3
TX Ben ... hat deine Sachen verfolgt ... tx für all die großartige Unterstützung auf RX
born2net
3
@ Hardul ... Sie würden das Ergebnis abonnieren:result.subscribe(value => doSomething(value))
Ben Lesh
2
@ BenTaliadoros Ja, jedes Mal, wenn Sie return subject.asObservable();es wäre, wäre es ein neues Observable. Sie hätten eine einzelne Subject-Mitgliedsvariable, und onMessage / onOtherMessage würde in einer Bedingung oder bei der Initialisierung (nicht bei jedem Aufruf) deklariert. Ich habe diesen Ansatz mit einem pipe( filter() )auf einem Parameter basierenden Parameter getData()verwendet. The
Drenai
5
@ BenLesh, soll in deinem zweiten Codebeispiel subjectsein subscriber?
Florin D
1
Ich möchte auch hier eine Überprüfung: sollten die subject.nextZeilen sein subscriber. "Wenn Sie das resultierende Observable erneut versuchen oder wiederholen, wird es nicht so funktionieren, wie Sie es sich vorstellen." Kannst du genauer sein? Meinst du nur, new SomeWeirdDataSource()dass es jedes Mal passieren wird, wenn getDataes aufgerufen wird, und wenn new Observabledu es einpackst, lässt du diese Instanziierung bis zu einem Abonnement warten. Ich glaube, ich sehe nicht, wann Sie getDataohne ein anrufen würden, .subscribealso fehlt mir dort der Wert. Was erwarten Sie schließlich, um "die Datenquelle abzureißen"? Vielen Dank.
1252748
7

A Subjectkann sowohl als Akt observerund ein observable.

An Obervablehat 2 Methoden.

  • abonnieren
  • Abmelden

Jedes Mal , wenn Sie abonnieren , um ein observable, erhalten Sie ein , observerdie hat nächste , Fehler und vollständige Methoden darauf.

Sie müssten die Sequenz ausblenden, da die Stream-Quelle nicht in jeder Komponente öffentlich verfügbar sein soll. Sie können sich auch auf @BenLeshdas Beispiel beziehen .

PS: Als ich zum ersten Mal durch Reactive Javascript kam, konnte ich es nicht verstehen asObservable. Weil ich sicherstellen musste, dass ich die Grundlagen klar verstehe und mich dann für etwas entschieden habe asObservable. :) :)

HV Sharma
quelle