RxJS递增验证事件流
问题描述:
我有一个带有字符串键和值的state
对象。事件进入,包含键值对来更改state
。RxJS递增验证事件流
我需要抖流说:
- 验证事件,并丢弃所有的修改中去抖周期,如果他们导致无效状态
- 的差异输出到最后一个有效的状态
例如,初始状态为{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
,但我无法弄清楚如何将流与其最后一个值进行配对。
答
感谢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()
你很可能需要使用['scan'](http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance - 方法扫描),但没有大理石图,这个问题不容易解释。 – cartant
谢谢,这指出我正确的方向。 – sashee