Paul D'Ambra
Paul D'Ambra

Reputation: 7814

Turn several ajax requests into Observables with RxJS

I'm struggling with something - which I'm guessing means I've misunderstood and am doing something silly

I have an observable and need to use it to create some object, send that to the server for processing, combine a result from the server with the object I sent, and then turn that into an observable so what I want to do (I think) is something like

var theNewObservable = my.observable.things.select(function(thing) {
            var dataToSend = generateMyJavascriptObjectFrom(thing);
            var promise = $.ajax({
                type: 'POST',
                url: http://somewhere.com,
                data: dataToSend
            }).promise();

            return rx.Observable.fromPromise(promise).subscribe(function(data, status, jqXHR) {
                var infoFromServer = jqXHR.getResponseHeader('custom-header-returned');
                    // I'm wanting this to be the thing other code can subscribe to
                return { infoFromServer: dataToSend };
            }, function(err) {
                alert('PC LOAD LETTER!');
                console.error(err);
            });
        }
});

theNewObservable.subscribe(function(combinedInfo) { console.log(combinedInfo) };

where I'm expecting {infoFromServer: dataToSend} I'm getting an AutoDetachObserver and I can see that has an onNext with the ajax onSuccess signature so I'm obviously doing something silly

Upvotes: 4

Views: 3320

Answers (1)

paulpdaniels
paulpdaniels

Reputation: 18663

A couple things that should help a bit:

1) The subscribe method is a terminal method, as in, it won't return anything. It is where the Observer attaches so there should be no further data propagation after the subscribe

2) The onNext method of subscribe can only take a single value which you will need to have all the message data wrapped in.

Since jQuery's Promise will not behave well with this, you have two options. First, you can use the RX-DOM project for an Observable ajax version. Or you will need to wrap the promise method. If you further need to wait on the response you should be using selectMany instead, which will allow you to fire off the promise, then await its return and map the response to the original request.

var theNewObservable = my.observable.things
          //Preprocess this so that `selectMany` will use 
          //dataToSend as the request object
          .map(function(thing) { return generateMyJavascriptObjectFrom(thing); })
          .selectMany(function(dataToSend) {
            var promise = $.ajax({
                type: 'POST',
                url: http://somewhere.com,
                data: dataToSend
            }).promise();

            //Rewrap this into a promise that RxJS can handle
            return promise.then(function(data, status, jqXHR) {
              return {data : data, status : status, jqXHR : jqXHR};
            });
          }, function(request, response) {
            return {
                    infoFromServer : response.jqXHR.getResponse('custom-header'),
                    dataToSend : request
                   };
          });

theNewObservable.subscribe(
  function(combinedInfo) { 
    console.log(combinedInfo) 
  },
  function(err) {
    alert('PC LOAD LETTER!');
    console.error(err);
  });

Upvotes: 4

Related Questions