Promise.all behavior with RxJS Observables?

JavascriptAngularjsRxjsObservable

Javascript Problem Overview


In Angular 1.x I would sometimes need to make multiple http requests and do something with all the responses. I would throw all the promises in an array and call Promise.all(promises).then(function (results) {...}).

Angular 2 best practices seem to point towards the use of RxJS's Observable as a replacement to promises in http requests. If I have two or more different Observables created from http requests, is there an equivalent to Promise.all()?

Javascript Solutions


Solution 1 - Javascript

The more straightforward alternative for emulating Promise.all is to use the forkJoin operator (it starts all observables in parallel and join their last elements):

A bit out of scope, but in case it helps, on the subject of chaining promises, you can use a simple flatMap : Cf. https://stackoverflow.com/questions/34701304/rxjs-promise-composition-passing-data/34701912#34701912

Solution 2 - Javascript

Update May 2019 using RxJs v6

Found the other answers useful, and wished to offer an example for the answer offered by Arnaud about zip usage.

Here is a snippet showing the equivalence between Promise.all and the rxjs zip (note also, in rxjs6 how zip now gets imported using "rxjs" & not as an operator).

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

The output from both are the same. Running the above gives:

{ 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!' ]

Solution 3 - Javascript

forkJoin works fine too, but I'd prefer combineLatest since you don't need to worry about it taking the last value of observables. This way, you can just get updated whenever any of them emit a new value too (e.g. you fetch on an interval or something).

Solution 4 - Javascript

On reactivex.io forkJoin actually points to Zip, which did the job for me:

let subscription = Observable.zip(obs1, obs2, ...).subscribe(...);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCorey OgburnView Question on Stackoverflow
Solution 1 - Javascriptuser3743222View Answer on Stackoverflow
Solution 2 - JavascriptarcseldonView Answer on Stackoverflow
Solution 3 - JavascriptkakigooriView Answer on Stackoverflow
Solution 4 - JavascriptArnaud PView Answer on Stackoverflow