Promise.all zachowanie z RxJS Observables?

91

W Angular 1.x czasami musiałem składać wiele httpżądań i robić coś ze wszystkimi odpowiedziami. Wrzuciłbym wszystkie obietnice do tablicy i zadzwonił Promise.all(promises).then(function (results) {...}).

Najlepsze praktyki Angular 2 wydają się wskazywać na użycie RxJS Observablejako zamiennika obietnic w httpżądaniach. Jeśli mam dwa lub więcej różnych Observables utworzonych na podstawie żądań http, czy istnieje odpowiednik Promise.all()?

Corey Ogburn
źródło

Odpowiedzi:

80

Bardziej prostą alternatywą emulacji Promise.alljest użycie forkJoinoperatora (uruchamia on wszystkie obserwable równolegle i łączy ich ostatnie elementy):

Trochę poza zakresem, ale na wypadek, gdyby to pomogło, w temacie łańcuchów obietnic, możesz użyć prostego flatMap: Por. RxJS Promise Composition (przekazywanie danych)

user3743222
źródło
1
Czy jeśli mam 2 połączenia, jedną obietnicę zwrotu i inną możliwą do zaobserwowania, mogę użyć forkjoin? lub obietnica.all ()? czy nikt, muszę pozwolić, aby 2 funkcje zwracały ten sam typ obietnice lub obserwowalne?
Joe Sleiman,
1
Proszę o pomoc, forkJoin nie działa, gdy obserwable przekazane jako parametr nie emitują wartości. Mam void Observables i nadal chcę korzystać z funkcji forkJoin, ale nie działa
Goga Koreli
19

Zaktualizuj maj 2019 przy użyciu RxJs v6

Inne odpowiedzi okazały się przydatne i chciałem podać przykład odpowiedzi udzielonej przez Arnaud na temat zipużycia.

Oto fragment pokazujący równoważność między Promise.allrxjs a rxjs zip(zwróć także uwagę, w rxjs6, w jaki sposób zip jest teraz importowany przy użyciu "rxjs", a nie jako operatora).

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

Dane wyjściowe z obu są takie same. Uruchomienie powyższego daje:

{ 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
źródło
Pracował dla mnie :)
Naveen Kumar V
12

forkJoin też działa dobrze, ale wolałbym kombajn najnowszy, ponieważ nie musisz się tym martwić, biorąc ostatnią wartość obserwabli. W ten sposób możesz być po prostu aktualizowany za każdym razem, gdy którykolwiek z nich również emituje nową wartość (np. Pobierasz w interwale lub coś takiego).

kakigoori
źródło
1
To nie odpowiada moim obecnym potrzebom, ale na pewno wkrótce z tego skorzystam.
Corey Ogburn
5
To nie zapewnia takiego samego zachowania jak Promise.all (), ale jest podobne do Promise.any ()
Purrell
Czy jeśli mam 2 połączenia, jedną obietnicę zwrotu i inną możliwą do zaobserwowania, mogę użyć forkjoin? lub obietnica.all ()? czy nikt, muszę pozwolić, aby 2 funkcje zwracały ten sam typ obietnice lub obserwowalne?
Joe Sleiman,
1
@JoeSleiman trochę spóźniony, ale możesz wybrać swoją stronę: Observable.fromPromise () razem z Observable.zip () lub Obserable.toPromise () z Promise.all ()
Arnaud P
11

Na widelcu reactivex.ioJoin wskazuje na Zip , który wykonał zadanie za mnie:

let subscription = Observable.zip(obs1, obs2, ...).subscribe(...);
Arnaud P
źródło
„oznacza to, że forkJoin nie wyemituje więcej niż raz i zakończy się po tym. Jeśli chcesz wyemitować połączone wartości nie tylko na koniec cyklu życia przekazanych obserwabli, ale także w trakcie jego trwania, wypróbuj zamiast tego funkcję connectLatest lub zip”. rxjs-dev.firebaseapp.com/api/index/function/forkJoin
Jeffrey Nicholson Carré
3
forkJoin czeka na zakończenie wszystkich obserwabli, podczas gdy zip emituje tablicę, gdy wszystkie dane wejściowe emitują pierwszą wartość. zip może emitować wiele razy. Jeśli masz wywołania http, nie ma to znaczenia.
hgoebl
Dobra, teraz rozumiem subtelność, wiwaty. Nie zdawałem sobie sprawy, że sekcje językowe się rozszerzają-_-
Arnaud P