Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rx fromPromise and retry

Tags:

rxjs

Why do you have to flatMap the fromPromise to get the retry to work ?
(The '/error' returns a status 500)

var responseStream = Rx.Observable.just('/error').
        flatMap(requestUrl => {
            return Rx.Observable.fromPromise(_this.$http.get(requestUrl));
    });

    responseStream.
        retry(3).
        subscribe(
        function (x) {
            console.log('Next: ' + x);
        },
        function (err) {
            console.log('Error: ' + err);
        },
        function () {
            console.log('Completed');
        });

I would like to cut on the ceremonial and just have:

Rx.Observable.fromPromise(_this.$http.get('error')).
        retry(3).
        subscribe(
        function (x) {
            console.log('Next: ' + x);
        },
        function (err) {
            console.log('Error: ' + err);
        },
        function () {
            console.log('Completed');
        }); 

In that second case the xhr call is only executed once.

like image 267
Brett Avatar asked Oct 12 '15 02:10

Brett


1 Answers

Because Promises don't have an API for retrying. fromPromise is just wrapping the Promise and making it emit through an Observable instead. When you call _this.$http.get('error') you have already created a Promise and it is already in flight, so there is no way to retry the promise without calling the method again.

The reason it works when wrapped with flatMap is because when you retry the Observable it is actually re-executing the method that generates the promise.

If verbosity is really hurting you, realize that many of the operators support Promises implicitly, without the need to call the fromPromise method.

So your example could be reduced down to

var responseStream = Rx.Observable.just('/error')
        .flatMap(requestUrl => _this.$http.get(requestUrl));

    responseStream
        .retry(3)
        .subscribe(
          (x) => console.log('Next: ' + x),
          (err) => console.log('Error: ' + err),
          () => console.log('Completed'));

Or even more simply using defer:

Observable.defer(() => _this.$http.get('/error'))
   .retry(3)
   .subscribe(
      (x) => console.log('Next: ' + x),
      (err) => console.log('Error: ' + err),
      () => console.log('Completed'));
like image 187
paulpdaniels Avatar answered Nov 02 '22 14:11

paulpdaniels