2017-04-13 72 views
4

我試圖重複一個請求,直到響應中有使用RxJS的數據,此時我想調用成功(或失敗)處理程序,但是我遇到了RxJS問題。這是我目前的做法:如何重複ajax請求,直到RxJS Observable滿足條件?

// ... redux-observable action observable 
.mergeMap(() => 
    fetchData() 
    .repeatWhen(response => 
     response.takeWhile(({ data }) => !data.length) 
     .of(response) 
    ) 
) 
.map(successFunction) 
.catch(failureFunction); 

免責聲明:我很新的RxJS ....

+1

那麼,什麼是預期的行爲,什麼是實際行爲? – user3743222

回答

4

這聽起來像你想壓制阿賈克斯的結果和重試,直到你得到你想要的答覆。我願意做它像這樣:所以首先我們檢查,如果數據是空的,如果它是拋出一個錯誤

// observable that will re-fetch each time it is subscribed 
const request = Observable.defer(() => fetchData()); 

// each time request produces its value, check the value 
// and if it is not what you want, return the request 
// observable, else return an observable with the response 
// use switchMap() to then subscribe to the returned 
// observable. 
const requestWithRetry = request.switchMap(r => 
    r.data.length ? Observable.of(r) : requestWithRetry); 
+0

布蘭登,我傻眼了。這是如何遞歸的?具有錯誤長度的第一個請求會導致'request'被再次訂閱,導致'fetchData'的新執行並訂閱該結果。但爲什麼這個結果會再次通過'switchMap'流動呢? – user3743222

+0

@ user3743222是的,你是對的。不知道我在想什麼。第一個版本應該返回'requestWithRetry'。 :facepalm: – Brandon

+0

我現在明白了。很簡約。現在我想知道堆棧是如何演變的。但在任何情況下,對於有限的再審,都不應該有任何問題。 – user3743222

3

空的數據是不是一個錯誤。 然後retryWhen可用於測試此錯誤並只要發生就重試。

.mergeMap(() => 
    fetchData() 
    .map(data => { 
     if (!data.length) { 
      throw 'no data'; 
     } 
     return data; 
    }) 
    .retryWhen(errors => errors.takeWhile(error => error === 'no data')) 
) 
.map(successFunction) 
.catch(failureFunction); 
+0

沒有辦法做到這一點沒有投擲? – seitzej

+0

'repeatWhen'的問題是你沒有訪問'data'。 'repeatWhen'中的選擇器只收到源的「onComplete」通知。因此,這使得它不適用於你的情況。 「repeatWhen」的邏輯是,你在該源完成時重新訂閱源,然後在獨立於該源的其他條件下重新訂閱源。 'retrywhen'的優點是錯誤通知允許傳遞參數。 'onComplete'通知不是這樣的情況 – user3743222

+0

@seitzej'retryWhen'只在潛在的observable進入錯誤狀態AFAIK時才起作用,這可以在投擲時完成,爲什麼這是一個問題? –