2017-06-25 20 views
0

我有一個帶有字符串鍵和值的state對象。事件進入,包含鍵值對來更改stateRxJS遞增驗證事件流

我需要抖流說:

  • 驗證事件,並丟棄所有的修改中去抖週期,如果他們導致無效狀態
  • 的差異輸出到最後一個有效的狀態

例如,初始狀態爲{k1: "v1"},事件爲{k2: "v2"},輸出{k2: "v2"}

但是對於事件:{k3: "v3"}{k4: "invalid"},請放棄這兩個更改。所以當一個新事件{k5: "v5"}進來時,k3鍵仍未定義。

我能實現它,但只有通過使用新的主題,保持的最後一個有效的狀態軌跡:

const lastValidState = new Rx.Subject(); 

const res = modifications 
    .buffer(debounce) 
    .withLatestFrom(lastValidState.startWith(state)) 
    .map(([mods, last]) => { 
    // calculate next state 
    return [Object.assign({}, last, ...mods), last]; 
    }).filter(([newState]) => { 
    // check new state 
    return Object.keys(newState).every((k) => !newState[k].startsWith("invalid")); 
    // update Subject 
    }).do(([newState]) => lastValidState.next(newState)).share() 
    .map(([newState, last]) => { 
    // output diff 
    return Object.assign({}, ...Object.keys(newState).filter((k) => newState[k] !== last[k]).map((k) => ({[k]: newState[k]}))) 
    } 
) 

此代碼工作得很好(jsfiddle),但我不喜歡新主題介紹。我更喜歡不依賴於此的解決方案,而只使用RxJS運營商。

我試過使用pairwise,但我無法弄清楚如何將流與其最後一個值進行配對。

+2

你很可能需要使用['scan'](http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance - 方法掃描),但沒有大理石圖,這個問題不容易解釋。 – cartant

+0

謝謝,這指出我正確的方向。 – sashee

回答

0

感謝cartant's comment,使用scan是要走的路。

唯一的竅門是使用distinctUntilChanged來防止發出無效更改。

修改後的代碼:jsfiddle

const res = modifications 
    .buffer(debounce) 
    .scan((last, mods) => { 
    const newState = Object.assign({}, last, ...mods); 
    const valid = Object.keys(newState).every((k) => !newState[k].startsWith("invalid")); 

    if (valid) { 
     return Object.assign({}, ...Object.keys(newState).filter((k) => newState[k] !== last[k]).map((k) => ({[k]: newState[k]}))); 
    }else { 
     return last; 
    } 
    }, state) 
    .distinctUntilChanged()