如何用rxjs观察多个对象属性的变化?

时间:2018-04-05 14:46:14

标签: javascript object properties rxjs observers

我想要使用rxjs观察更改的对象。该对象具有多个属性,当它们中的任何一个发生更改时,我希望收到有关其中一个已更改以及其新值的通知。我已将我的代码的以下简化版本放在一起,但它并没有按预期工作:http://jsbin.com/sidukulowi/1/edit?js,console

const store = Rx.Observable.create(function(observer) {
  let state = { userActions: {
    window: {
      leftPanelWidth: 300,
      backgroundColor: 0xffffff,
    }
  }};

  observer.next(state);

  state = { userActions: {
    window: {
      leftPanelWidth: 250,
      backgroundColor: 0xffffff,
    }
  }};

  observer.next(state);

  state = { userActions: {
    window: {
      leftPanelWidth: 250,
      backgroundColor: 0xff00ff,
    }
  }};

  observer.next(state);
});


const subscribe = store
  .map( state => state.userActions.window )
  .distinctUntilChanged( ( a, b ) => {
    return a.leftPanelWidth === b.leftPanelWidth && a.backgroundColor === b.backgroundColor
  })
  .subscribe(val => console.dir(val));

当上面的代码运行时,我正确地得到更新,告诉我窗口对象中的某些内容何时发生了变化,但是我不知道如何找出哪个属性发生了变化。

我如何修改此内容,以便在第一次更改中看到leftPanelWidth300更改为250,并且在下一次更改中,它是backgroundColor已从0xffffff更改为0xff00ff

1 个答案:

答案 0 :(得分:1)

我才开始学习RxJX Observable。所以这可能不是最简单的解决方案。

但您可以使用distinctUntilChanged代替pairwise来检查之前的&当前价值。

例如

const store = Rx.Observable.create(function(observer) {
  let state = { userActions: {
    window: {
      leftPanelWidth: 300,
      backgroundColor: 0xffffff,
    }
  }};
  
  observer.next(state);
  
  state = { userActions: {
    window: {
      leftPanelWidth: 250,
      backgroundColor: 0xffffff,
    }
  }};
  
  observer.next(state);
  //lets add again to make sure it only when
  //changed..
  observer.next(state); 
  
  state = { userActions: {
    window: {
      leftPanelWidth: 250,
      backgroundColor: 0xff00ff,
    }
  }};
  
  observer.next(state);
  
});


const subscribe = store
  .map(a => a.userActions.window)
  .pairwise()
  .map(([a,b]) => 
    Object.entries(a)
      .filter(([k,v]) => b[k] !== v)
      .map(([k,v]) => ({
        property: k,
        old: a[k],
        new: b[k]
      }))
  )
  .filter(a => a.length)
  .subscribe(val => console.dir(val));

console.log( '--------------Done--------------' );
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.8/Rx.min.js"></script>