2017-08-04 96 views
2

我正在嘗試創建一個簡單的可重構可觀察史詩,它可以反彈並且可以取消。我的代碼:反彈和取消可重複觀察

export const apiValidate = action$ => { 
    return action$.ofType(validateRequestAction) 
     .debounceTime(250) 
     .switchMap((action) => (
      Observable.ajax({ 
       url: url, 
       method: 'GET', 
       crossDomain: true, 
       headers: { 
        "Content-Type": 'application/json' 
       }, 
       responseType: 'json' 
      }) 
      .map(payload => (new APISuccessValidate())) 
      .takeUntil(action$.ofType(validateCancelAction)) 
      .catch(payload => ([new APIFailureValidate()])) 
    )); 
}; 

代碼只有時纔有效。根據服務器的響應速度,我認爲可能會出現兩種情況之一。

情景1(作品):

Time 0ms - Fire validateRequestAction 
Time 250ms - Ajax request occurs 
Time 251ms - Fire validateCancelAction 
Time 501ms - validateCancelAction passes debounce and cancels properly 
Nothing else occurs 

方案2(斷)

Time 0ms - Fire validateRequestAction 
Time 250ms - Ajax request occurs 
Time 251ms - Fire validateCancelAction 
Time 400ms - Ajax returns, APISuccessValidate action fired 
Time 501ms - validateCancelAction passes debounce and there is nothing to cancel 

有沒有一種方法,我可以寫我的史詩,使得只有validateCancelAction可以繞過debounceTime並取消阿賈克斯呼籲沒有等待?

謝謝!

回答

3

你實際上只是在清除你的匹配validateRequestAction,但你的.takeUntil(action$.ofType(validateCancelAction))沒有任何反彈。我可能是錯的,但是如果可以在之前發送取消動作該動作已經超過了去抖動,那麼取消該動作將會取消而不是,因爲ajax請求沒有取消開始了,也沒有takeUntil。通過不允許取消直到你的副作用(本例中的ajax)已經開始並且takeUntil正在傾聽可能的取消。

在您的用戶界面中,您不會讓用戶能夠取消,直到設置了某種狀態爲止。由於我們的史詩需要告訴redux何時翻轉,我們需要發出一個動作,我們將在減速器中偵聽。

最簡單的方法是使用startWith操作:

export const apiValidate = action$ => { 
    return action$.ofType(validateRequestAction) 
     .debounceTime(250) 
     .switchMap((action) => (
      Observable.ajax({ 
       url: url, 
       method: 'GET', 
       crossDomain: true, 
       headers: { 
        "Content-Type": 'application/json' 
       }, 
       responseType: 'json' 
      }) 
      .map(payload => (new APISuccessValidate())) 
      .takeUntil(action$.ofType(validateCancelAction)) 
      .catch(payload => ([new APIFailureValidate()])) 
      .startWith({ type: 'validateRequestActionStarted' }) // <-- here 
    )); 
}; 

因此,在這個例子中,一些減速會聽validateRequestActionStarted,並改變一些國家的UI便會知道,我們應該給他們取消的能力。


阻止那場比賽將是takeUntil的頂級流完全和一個完全不同的方式則剛剛「重啓」使用repeat,如果它被取消的史詩。所以這會在我們取消時關閉所有的東西。任何懸而未決的ajaxs和任何未決的debounces。

export const apiValidate = action$ => { 
    return action$.ofType(validateRequestAction) 
     .debounceTime(250) 
     .switchMap((action) => (
      Observable.ajax({ 
       url: url, 
       method: 'GET', 
       crossDomain: true, 
       headers: { 
        "Content-Type": 'application/json' 
       }, 
       responseType: 'json' 
      }) 
      .map(payload => (new APISuccessValidate())) 
      .catch(payload => ([new APIFailureValidate()])) 
     )) 
     .takeUntil(action$.ofType(validateCancelAction)) 
     .repeat(); 
}; 

值得一提的是,我使用的術語史詩,並重新啓動,以幫助我們的概念化特定領域,但這大多隻是正常RxJS所以它的終極版,可觀察到的普遍適用的外面。一個「史詩」只是我們的一個函數模式的一個詞,它接受一系列操作(輸入)並返回一系列操作(輸出)。

+0

感謝您花時間解釋我對抖動動作的誤解,這對我幫助了很多,正確理解了這個問題。我嘗試了你提供的第二個解決方案,它完美的工作!我也不知道startWith,我相信這將在未來派上用場。 非常感謝! –

+0

不客氣!我強烈建議花一些時間真正理解_why_它的作品:)祝你好運! – jayphelps

+0

是的,我現在正在通過所有文檔工作=) –