jhamm
jhamm

Reputation: 25032

How do I send multiple http requests with rx.js?

I am trying out rx.js and I am trying to make multiple http request. Here is the observable that I have set up to make the http request.

function httpGet(url) {
    return Observable.create(function forEach(observer) {
        var cancelled = false;
        axios.get(url).then(function(res) {
            if(!cancelled) {
                observer.onNext(res);
                observer.onCompleted();             
            }
        });

        return function dispose() {
            cancelled = true;
        }
    })
}

I am trying to make multiple http requests, but my result is more Observable's. Here is the subscribe:

var array = ['http://localhost:4444/text/88', 'http://localhost:4444/other/77'];

var source = Rx.Observable.fromArray(array).map(httpGet);

var subscription = source.subscribe(
    function (x) {
        console.log(x);
    },
    function (err) {
        console.log('Error: ' + err);
    },
    function () {
        console.log('Completed');
});

And here is my result.

AnonymousObservable { source: undefined, __subscribe: [Function: forEach] }
AnonymousObservable { source: undefined, __subscribe: [Function: forEach] }
Completed

I understand that I am getting Observable's and if I forEached through them, then I would get the result, but I am missing the proper way of transforming this into data and not an Observable. What am I doing wrong?

Upvotes: 3

Views: 4915

Answers (1)

user3743222
user3743222

Reputation: 18665

That should do the trick:

var array = ['http://localhost:4444/text/88', 'http://localhost:4444/other/77'];

var source = Rx.Observable.fromArray(array).concatMap(httpGet);

function httpGet(url) {
  return axios.get(url);
  }
var subscription = source.subscribe(
    function (x) {
        console.log(x);
    },
    function (err) {
        console.log('Error: ' + err);
    },
    function () {
        console.log('Completed');
});

Some explanations:

  • an observable is a sequence of values. An observer is a three-pronged object which processes those values.
  • what you want is turn the array (source) into a sequence of html (obtained from fetching the urls). What you have at your disposal is :
  • you then want to subscribe to the produced sequences and do something with them. That is the subscribe function where you define your observer.
  • so here you take your sequence of array values, produce a sequence of promises with the map operator, BUT actually you will use the concatMap operator to output the promise resolved values in the same order than the array values. concatMap can take an observable, an array/iterable or a promise as its argument, and will output the sequence of values wrapped into those objects in the observable it returns. So instead of having a sequence of promises you have a sequence of values resolved by the promises i.e. your fetched html content. If you are not interested in keeping the initial ordering of the source, you could also use the flatMap operator. Cf. https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/concatmap.md and https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/selectmany.md
  • then you subscribe to that, and process those values

So this is basically the general process, you take a source sequence, turn that into a sequence of your choice through a judicious choice of operators, and then process the values one by one with your observer function. Also, note that a promise is akin to an observable, and some (most?) Rxjs operators will treat them as such, so you often do not have to use then to get the resolved value.

Last thing, Rx.Observable.fromArray seems to be deprecated in favor of Rx.Observable.from : cf. https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/fromarray.md

Upvotes: 12

Related Questions