RxJS递增验证事件流

RxJS递增验证事件流

问题描述:

我有一个带有字符串键和值的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

感谢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()