我有一个带有字符串键和值的state
对象。事件即将发生,包含用于更改state
的键值对。
我需要一个debounced流:
例如,对于{k1: "v1"}
的初始状态和{k2: "v2"}
的事件,请输出{k2: "v2"}
。
但对于事件:{k3: "v3"}
和{k4: "invalid"}
,请删除这两项更改。因此,当新事件{k5: "v5"}
进入时,k3
键仍未定义。
我能够实现它,但只能使用跟踪上一个有效状态的新主题:(jsfiddle)
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]})))
}
)
此代码效果很好,但我不喜欢它引入的新主题。我更喜欢不依赖于此的解决方案,只使用RxJS运算符。
我已尝试使用pairwise
,但我无法弄清楚如何将流与其自身的最后一个值配对。
答案 0 :(得分:0)
感谢here,使用scan
即可。
唯一的诀窍是使用distinctUntilChanged
来防止发出无效更改。
修改后的代码:cartant's comment
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()