Promise.all Verhalten mit RxJS Observables?

83

In Angular 1.x musste ich manchmal mehrere httpAnfragen stellen und mit allen Antworten etwas anfangen. Ich würde alle Versprechen in ein Array werfen und anrufen Promise.all(promises).then(function (results) {...}).

Best Practices für Angular 2 scheinen auf die Verwendung von RxJS Observableals Ersatz für Versprechen in httpAnfragen hinzuweisen . Wenn ich zwei oder mehr verschiedene Observables aus http-Anfragen erstellt habe, gibt es eine Entsprechung zu Promise.all()?

Corey Ogburn
quelle

Antworten:

77

Die einfachere Alternative zum Emulieren Promise.allbesteht darin, den forkJoinOperator zu verwenden (er startet alle Observablen parallel und verbindet ihre letzten Elemente):

Ein bisschen außerhalb des Anwendungsbereichs, aber falls es beim Verketten von Versprechungen hilft, können Sie ein einfaches verwenden flatMap: Vgl. RxJS Promise Composition (Daten übergeben)

user3743222
quelle
1
Wenn ich 2 Anrufe habe, ein Rückgabeversprechen und eine andere beobachtbare Rückgabe, kann ich Gabel verbinden? oder versprechen.all ()? oder niemand, ich muss die 2 Funktionen den gleichen Typ zurückgeben lassen, entweder versprochen oder beobachtbar?
Joe Sleiman
1
Bitte helfen Sie, forkJoin funktioniert nicht, wenn als Parameter übergebene Observables keine Werte ausgeben. Ich habe void Observables und möchte immer noch die forkJoin-Funktionalität verwenden, aber es funktioniert nicht
Goga Koreli
16

Update Mai 2019 mit RxJs v6

Fanden die anderen Antworten nützlich und wollten ein Beispiel für die Antwort von Arnaud zur zipVerwendung geben.

Hier ist ein Ausschnitt, der die Äquivalenz zwischen Promise.allund den rxjs zeigt zip(beachten Sie auch in rxjs6, wie zip jetzt mit "rxjs" und nicht als Operator importiert wird).

import { zip } from "rxjs";

const the_weather = new Promise(resolve => {
  setTimeout(() => {
    resolve({ temp: 29, conditions: "Sunny with Clouds" });
  }, 2000);
});

const the_tweets = new Promise(resolve => {
  setTimeout(() => {
    resolve(["I like cake", "BBQ is good too!"]);
  }, 500);
});

// Using RxJs
let source$ = zip(the_weather, the_tweets);
source$.subscribe(([weatherInfo, tweetInfo]) =>
  console.log(weatherInfo, tweetInfo)
);

// Using ES6 Promises
Promise.all([the_weather, the_tweets]).then(responses => {
  const [weatherInfo, tweetInfo] = responses;
  console.log(weatherInfo, tweetInfo);
});

Die Ausgabe von beiden ist gleich. Wenn Sie die oben genannten Schritte ausführen, erhalten Sie:

{ temp: 29, conditions: 'Sunny with Clouds' } [ 'I like cake', 'BBQ is good too!' ]
{ temp: 29, conditions: 'Sunny with Clouds' } [ 'I like cake', 'BBQ is good too!' ]
arcseldon
quelle
13

forkJoin funktioniert auch gut, aber ich würde kombinierenLatest bevorzugen, da Sie sich keine Sorgen machen müssen, dass der letzte Wert von Observablen verwendet wird. Auf diese Weise können Sie einfach aktualisiert werden, wenn einer von ihnen auch einen neuen Wert ausgibt (z. B. wenn Sie ein Intervall oder etwas abrufen).

kakigoori
quelle
1
Dies entspricht nicht meinen aktuellen Anforderungen, aber ich werde es definitiv bald nutzen.
Corey Ogburn
4
Das erreicht nicht das gleiche Verhalten wie Promise.all (), aber es ähnelt Promise.any ()
Purrell
Wenn ich 2 Anrufe habe, ein Rückgabeversprechen und eine andere beobachtbare Rückgabe, kann ich Gabel verbinden? oder versprechen.all ()? oder niemand, ich muss die 2 Funktionen den gleichen Typ zurückgeben lassen, entweder versprochen oder beobachtbar?
Joe Sleiman
@ JoeSleiman etwas spät, aber Sie können Ihre Seite auswählen: Observable.fromPromise () zusammen mit Observable.zip () oder Obserable.toPromise () mit Promise.all ()
Arnaud P
10

Auf reactivex.io zeigt forkJoin tatsächlich auf Zip , was die Arbeit für mich erledigt hat:

let subscription = Observable.zip(obs1, obs2, ...).subscribe(...);
Arnaud P.
quelle
"Das bedeutet, dass forkJoin nicht mehr als einmal ausgegeben wird und danach abgeschlossen wird. Wenn Sie kombinierte Werte nicht nur am Ende des Lebenszyklus übergebener Observablen, sondern auch während des gesamten Lebenszyklus ausgeben müssen, probieren Sie stattdessen combinLatest oder zip aus." rxjs-dev.firebaseapp.com/api/index/function/forkJoin
Jeffrey Nicholson Carré
1
forkJoin wartet auf das Ende aller Observablen, während zip ein Array ausgibt, wenn alle Eingaben ihren ersten Wert ausgeben. zip kann viele Male ausgeben. Wenn Sie http-Anrufe haben, macht es keinen Unterschied.
hgoebl
Richtig, ich verstehe jetzt die Subtilität, Prost. Ich hatte nicht bemerkt, dass die Sprachabschnitte erweitert werden-_-
Arnaud P