2015-10-12 18 views
9

Perché devi per flatMap il fromPromise per ottenere il tentativi al lavoro?
(Il '/ error' restituisce lo stato 500)Rx fromPromise e riprovare

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

vorrei tagliare il cerimoniale e solo:

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 questo secondo caso la chiamata XHR è solo eseguito una volta.

risposta

20

Perché Promises non dispone di un'API per riprovare. fromPromise sta semplicemente avvolgendo lo Promise e lo fa emettere tramite un Observable. Quando chiami _this.$http.get('error') hai già creato un Promise ed è già in volo, quindi non c'è modo di riprovare la promessa senza chiamare nuovamente il metodo.

Il motivo per cui funziona quando viene eseguito il wrapping con flatMap è dovuto al fatto che quando si riprova il Observable si sta effettivamente rieseguendo il metodo che genera la promessa.

Se la verbosità ti fa davvero male, renditi conto che molti operatori supportano implicitamente Promises, senza la necessità di chiamare il metodo fromPromise.

Così il vostro esempio può essere ridotta fino al

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

o anche più semplicemente usando defer:

Observable.defer(() => _this.$http.get('/error')) 
    .retry(3) 
    .subscribe(
     (x) => console.log('Next: ' + x), 
     (err) => console.log('Error: ' + err), 
    () => console.log('Completed')); 
+0

Grazie questo è esattamente quello che stavo cercando! – Brett

+0

@paulpdaniels posso semplicemente racchiudere la promessa in una funzione semplice e quindi fornire quella di fromPromise come: Rx.Observable.fromPromise (getRequest) .retry .... dove getRequest è una funzione semplice che restituisce la promessa. ovvero: function getRequest() {return _this. $ http.get ('/ error')); } –

+0

@ShaileshVaishampayan dipende dalla versione di RxJS che si sta utilizzando. RxJS 4 ti permette di passare le funzioni a 'fromPromise' che sono pigramente valutate al momento dell'iscrizione, ma manca in RxJS 5. In entrambi i casi,' defer' funziona in entrambi i casi – paulpdaniels