web-dev-qa-db-de.com

Was sind die Unterschiede zwischen Observables und Versprechungen in JavaScript?

Ich habe also gelesen, dass Observables versuchen werden, Versprechen hinsichtlich der Verwendung in einigen der kommenden JavaScript-MVCs zu überholen:

Was ist der Unterschied zwischen Observablen und Versprechen?

Aktualisiert: Entschuldigung! meine falsche Aussage entfernt.

30
chrisjlee

Was ist der Unterschied zwischen Observablen und Versprechen?

Einfach ausgedrückt: Ein Versprechen löst sich asynchron in einen single -Wert auf, ein Observable löst (oder emittiert) multiple -Werte asynchron (über die Zeit) ab.

Konkrete Beispiele:

  • Versprechen: Antwort von einem Ajax-Anruf
  • Beobachtbar: Klicken Sie auf Ereignisse

Weitere Informationen finden Sie hier: http://reactivex.io/intro.html

ich habe gelesen, dass Observables Versprechen einlösen wollen

Unwahrscheinlich. Observables sind vielleicht die bessere Lösung für bestimmte Probleme, aber das macht Versprechen nicht obsolet (wenn Sie das meinen).

29
Felix Kling

Versprechungen sind eine Darstellung eines zukünftigen Wertes . Beobachtbare Werte sind eine Darstellung für eine möglicherweise unendliche Anzahl von Werten. 

Versprechen lösen den Abruf dieses Wertes sofort nach der Erstellung aus. Observables werden nur dann mit der Erstellung von Werten beginnen, wenn Sie sie abonnieren. (Es sei denn, es ist ein heißer beobachtbarer Beobachter, aber das ist nicht Gegenstand dieser Frage.)

Versprechen sollen AJAX -Aufrufe darstellen. Observables können alles darstellen: Ereignisse, Daten aus Datenbanken, Daten aus Ajax-Aufrufen, (möglicherweise unendliche) Sequenzen usw.

33
Moeri

Promises bieten einen sehr vereinfachten Rückrufmechanismus, bei dem Rx eine starke Abstraktion gegenüber asynchroner Programmierung bietet. Ein Observable stellt einen Datenstrom dar, auf den wir Operatoren anwenden können, um festzulegen, wie die eingehenden Daten behandelt werden sollen.

Wenn Sie lediglich eine HTTP-Anforderung erstellen und dann eine UI-Komponente aktualisieren möchten, reicht es möglicherweise aus, eine Promise zu verwenden.

Die meisten Apps haben jedoch kompliziertere Anforderungen (auch wenn dies zunächst nicht offensichtlich ist). Schauen wir uns beispielsweise unsere HTTP-Anfrage an, um herauszufinden, wie die Modellierung als Observable und die Verwendung einiger Rx-Operatoren uns helfen können:

-Wenn die HTTP-Anfrage durch eine Benutzeraktion ausgelöst wird, möchten wir möglicherweise vorsichtig sein, mehrere HTTP-Anfragen abzustoßen (stellen Sie sich einen Benutzer vor, der in ein Suchfeld eingibt). Wir möchten nicht für jeden Tastendruck eine Anfrage auslösen, daher möchten wir vielleicht Drosseln unsere Suche, sodass wir nur dann eine Anfrage auslösen, wenn der Benutzer 300ms lang nicht mehr tippt. Wenn der Benutzer ein Word eingibt, 300 ms wartet und ein anderes Zeichen hinzufügt, lösen wir eine nachfolgende HTTP-Anforderung aus. Bei Versprechungen stoßen wir wahrscheinlich auf eine Wettlaufsituation, da wir nicht die Reihenfolge steuern können, in der wir die Antworten erhalten und alte Anfragen nicht stornieren können. Rx löst dies, indem wir Switch zwischen Streams zulassen, wodurch Dispose für die alten Anforderungsabonnements aufgerufen wird, die uns nicht mehr interessieren. Möglicherweise filtern wir auch ungültige Sucheingaben, z. B. Wo der Suchbegriff weniger als 3 Zeichen umfasst.

-Unterstützung für den Umgang mit Timeouts/Fehlerbehandlung. Angenommen, unsere HTTP-Anforderung schlägt fehl. Mit Rx können Sie die Anforderung einfach Retry ausführen.

-Angenommen, mehrere Teile unserer Anwendung müssen denselben HTTP-Aufruf durchführen. Wir möchten den Aufruf wahrscheinlich nicht mehr als einmal durchführen. Wir können unser Observable für mehrere Verbraucher freigeben und mit Replay sicherstellen, dass der Anruf einmal erfolgt und das Ergebnis für nachfolgende Teilnehmer zwischengespeichert wird. Wir können sogar ein TimeSpan für Replay bereitstellen, wodurch das Cache-Verhalten abläuft.

- Leistungsfähige Abstraktion über Threading durch die Verwendung von Schedulern, wodurch wir die Parallelität steuern können. Noch besser: Wir können Test-Scheduler in unseren Unit-Tests verwenden, um die Zeit zu steuern, sodass wir Timeouts, Rennbedingungen usw. simulieren können.

Dies sind einige schnelle Beispiele, die zeigen, was möglich ist. Es gibt viele weitere Operatoren innerhalb des Rx-Frameworks, die für alle Arten von Szenarien geeignet sind. Durch die Zusammenstellung von Rx können Sie einfach Operatoren kombinieren, um das gewünschte Verhalten zu definieren. Sie können auch leicht eigene wiederverwendbare Operatoren erstellen (z. B. RetryAfterDelay).

Zusammenfassend kann Rx alles tun, was Promises kann, und weit mehr. Ich vermute, dass es in den nächsten Jahren eine weitere Verschiebung hin zu Rx statt zu Versprechen geben wird. 

Um weiter zu lesen, empfehle ich einen Blick auf den Abschnitt Observables in der Angular 2-Anleitung .

24
domino

wie gesagt in Angular 2 Guid

Das Konvertieren in ein Versprechen ist oft eine gute Wahl, wenn Sie einen einzelnen Datenblock abrufen möchten. Wenn Sie die Daten erhalten, sind Sie fertig.

In einigen Fällen werden Anfragen jedoch nicht immer nur einmal ausgeführt. Sie können eine Anfrage starten, abbrechen und eine andere Anfrage stellen, bevor der Server auf die erste Anfrage reagiert hat.

zum Beispiel in einer Suchkomponente Wenn der Benutzer einen Namen in ein Suchfeld eingibt, werden von dieser Suchabfrage wiederholte HTTP-Anforderungen gestellt.

Eine Request-Cancel-New-Request-Sequenz ist mit .__ schwer zu implementieren. Versprechungen, aber einfach mit Observables.

wenn Ihre Komponente Daten mit nur einer Anforderung erhält, ist es eine gute Wahl, Promise zu verwenden. Wenn es jedoch eine Kette von request-cancel-new-Anforderungen gibt, sollten Sie observable

6
Parid0kht

Observables werden oft mit Versprechungen verglichen. Hier einige wichtige Unterschiede:

Observables sind deklarativ; Die Berechnung beginnt erst beim Abonnement. Versprechen werden sofort nach der Erstellung ausgeführt. Dies macht Observables nützlich, um Rezepte zu definieren, die ausgeführt werden können, wenn Sie das Ergebnis benötigen.

Observables liefern viele Werte. Versprechen geben einen. Dies macht Observables nützlich, um über die Zeit mehrere Werte zu erhalten.

Observables unterscheiden zwischen Verkettung und Abonnement. Versprechen haben nur .then () - Klauseln. Dies macht Observables zum Erstellen komplexer Transformationsrezepte, die von anderen Teilen des Systems verwendet werden sollen, ohne dass die Arbeit ausgeführt wird.

Observables subscribe () ist für die Behandlung von Fehlern verantwortlich. Versprechungen Push-Fehler zu den Versprechen des Kindes. Dies macht Observables für die zentrale und vorhersagbare Fehlerbehandlung hilfreich.

Beste Erklärung von eckig auf der offiziellen Website: 

https://angular.io/guide/comparing-observables

1
asad mohd

Observables VS. Promises (von Jeremy Vilken)

Zusätzlich zur neuen Syntax ist observables ein neueres Muster für JavaScript-Anwendungen, um asynchrone Aktivitäten zu verwalten. Sie sind auch ein Entwurf für ein Feature, das nativ in der JavaScript-Sprache implementiert werden soll, sodass es Gewicht hinter dem Muster hat. RxJS ist die Bibliothek, mit der wir Observables in unseren Anwendungen implementieren können.

Promises sind ein weiteres Konstrukt, um mit asynchronen Aufrufen umzugehen, die zum Beispiel für API-Anforderungen nützlich sind. Versprechungen haben eine wesentliche Einschränkung, da sie nur für einen Anrufzyklus nützlich sind. Wenn Sie beispielsweise möchten, dass ein Versprechen bei einem Ereignis wie einem Klick eines Benutzers einen Wert zurückgibt, wird dieses Versprechen beim ersten Klick aufgelöst. Sie könnten jedoch daran interessiert sein, jede Benutzer-Klick-Aktion zu handhaben. Normalerweise verwenden Sie hierfür einen Ereignis-Listener, mit dem Sie Ereignisse im Laufe der Zeit verarbeiten können. Dies ist ein wichtiger Unterschied: Observables sind wie Event-Handler dahingehend, dass sie Daten über einen längeren Zeitraum weiter verarbeiten und es Ihnen ermöglichen, diesen Datenstrom kontinuierlich zu verarbeiten.

1
Masoud Bimar

Wenn Sie Observables richtig verstehen, sind die Unterschiede zu Promises ziemlich offensichtlich. 

Die Entmystifizierung eines komplizierten Konzepts ist am besten, wenn Sie es von Grund auf neu implementieren. Hier ist eine fast rein funktionale Observable-Implementierung und ein Beispiel, das mit Promises nicht funktionieren würde:

/*** Observable type ***/

// type constructor (of a product type)

const proType = name => cons => {
  const f = (k, ...args) =>
    Object.defineProperties({["run" + name]: k}, {
      [Symbol.toStringTag]: {value: name},
      [Symbol("args")]: {value: args}
    });

  return cons(f);
};

// value constructor

const Observable = proType("Observable")
  (Observable => k => Observable(k));

/*** Observer factory ***/

const Observer = observer => {
  let isUnsubscribed = false;

  return {
    next: function(x) {
      if (isUnsubscribed)
        throw new Error("unsubscribed");

      else {
        try {
          return observer.next(x);
        }

        catch(e) {
          isUnsubscribed = true;
          this.cancel();
          throw e;
        }
      }
    },

    error: function(e) {
      if (isUnsubscribed)
        throw new Error("unsubscribed");

      else {
        try {
          return observer.error(e);
        }

        catch(e_) {
          isUnsubscribed = true;
          this.cancel();
          throw e_;
        }
      }
    },

    complete: function() {
      if (isUnsubscribed)
        throw new Error("unsubscribed");

      else {
        try {
          const r = observer.complete();
          this.cancel();
          return r;
        }

        catch(e) {
          isUnsubscribed = true;
          cancel();
          throw e;
        }
      }
    }
  };
};

/*** combinators + auxiliary functions ***/

const subscribe = observable => handlers => {
  const observer = Observer(handlers),
    cancel = observable.runObservable(observer);

  observer.cancel = cancel;
  return cancel;
};

const obsMap = f => observable =>
  Observable(observer => {
    const mapObserver = {
      next: x => observer.next(f(x)),
      error: e => observer.error(e),
      complete: () => observer.complete()
    };

    return observable.runObservable(mapObserver);
  });

/*** main ***/

// create an Observable instance

const numStream = Observable(observer => {
  let i = 0;

  const timer = setInterval(() => {
    observer.next(i++);
  }, 1000);
  
  return () => clearTimeout(timer);
});

// map a function over it

const squaredNumStream =
  obsMap(x => x * x) (numStream);

// run the observable

const cancel = subscribe(squaredNumStream) ({
  next: x => console.log(x),
  error: e => console.error(e),
  complete: () => console.log("finished")
});

// cancel it

setTimeout(cancel, 11000);

Im obigen Beispiel gibt ObservablesquaredNumStream einen Strom von theoretisch unendlichen Werten asynchron aus. Mit Promises ist dies nicht möglich, da sie einen einzelnen zukünftigen Wert darstellen.

Ich hätte leicht eine andere squaredNumStream abonnieren können, ohne dass sich beide Instanzen gegenseitig stören. Dies liegt daran, dass Observables Unicast ist, wohingegen Promises Multicast ist.

squaredNumStream wird nicht zur Deklarationszeit ausgeführt, sondern nur nach der Subskription, da Observables langsam ausgewertet wird. Promises hingegen werden eifrig ausgewertet, das heißt, sie werden ausgeführt, sobald Sie sie erstellen.

Und schließlich können Observables vom Design aus aufgehoben werden, wohingegen Promises aufgrund der Unicast-Semantik nur schwer abzubrechen ist.

0
user10675354