0

I have a buggy Web service that sporadically sends a 500-error "XMLHttpRequest cannot load http://54.175.3.41:3124/solve. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://local.xxx.me:8080' is therefore not allowed access. The response had HTTP status code 500."

I use Bacon.retry to wrap the ajax call. When it fails, it'll just retry. However, what I notice is that the stream won't produce a value when the server fails. It's as if Bacon.retry doesn't retry (which is in fact what's happening, when I look under the hood in the dev console).

I'm using BaconJS 0.7.65.

The observable Bacon.retry looks like this:

  var ajaxRequest = Bacon.fromPromise($.ajax(//...));

  var observable = Bacon.retry({
      source: function() { return ajaxRequest; },
      retries: 50,
      delay: function() { return 100; }
    });

The code that calls the observable looks like this:

 stream.flatMap(function(valuesOrObservables) {
      return Bacon.fromArray(valuesOrObservables)
         .flatMapConcat(function(valueOrObservable) {

           switch(valueOrObservable.type) { //we calculate this beforehand
              case 'value' :
                return valueOrObservable.value;
              case 'observable' :
                return Bacon.fromArray(valueOrObservable.observables)
                            .flatMapConcat(function(obs) { return obs; })
           }
         })
 })

Observations:

  1. if I add an error handler to the observable, it still does not work.
  2. for some reason, #retry is called 50 times even when it succeeds.
U Avalos
  • 6,538
  • 7
  • 48
  • 81
  • What paulpdaniels said is right in Bacon as well, the `source` parameter should be a function that creates a *new* stream every time it is called - in this case a new `Bacon.$.ajax` stream. – OlliM Jul 02 '15 at 08:13

1 Answers1

2

I'm not sure entirely about Bacon but in RxJS Ajax calls are usually wrapped around AsyncSubjects so re subscribing to an error'd stream will just fire off the same error, you generally have to re-execute the method that produces the observable.

So something like retry would be (again sorry this is in Rx):

Rx.Observable.defer(() => callAjaxReturnObservable())
             .retry(50)
             .subscribe();

EDIT 1

Trying Baconize this and clarify my earlier answer:

var observable = Bacon.retry({
 source : function() { return Bacon.fromPromise($.ajax(/**/)); },
 retries : 50,
 delay: function() { return 100; }
});

If you don't have the fromPromise inside of the source function, then every time you retry the downstream will just receive the same exception.

paulpdaniels
  • 18,395
  • 2
  • 51
  • 55
  • Not sure I understand what you mean. Are you saying retry won't retry an error? Or that it's hooked up wrong? – U Avalos Jul 02 '15 at 16:10
  • 1
    I am saying its hooked up wrong, the actual call is made when you wrap the promise, resubscribing to promises just returns the stored value or error of the promise. To execute the Ajax again you need to rerun the whole `Bacon.fromPromise(/**/)` line – paulpdaniels Jul 02 '15 at 16:29
  • So you're saying do *not* wrap the ajax request in a promise? Might be easier to expand your answer with correct code. – U Avalos Jul 02 '15 at 18:06