RxJS逐步验证事件流

时间:2017-06-25 09:35:35

标签: rxjs rxjs5

我有一个带有字符串键和值的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,但我无法弄清楚如何将流与其自身的最后一个值配对。

1 个答案:

答案 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()