如何使用rxjs观察对象更改5

时间:2017-06-05 12:52:32

标签: javascript rxjs rxjs5

我想查看一个对象,因此所有订阅者都会收到通知。

我看到它已经asked before了, 然而答案是无关紧要的,因为RXjs版本5不再包含其API中的 ofObjectChanges

我看过一些" hacks"比如创建一个返回函数的观察者:

let myObservable =  new Observable((observer) => {
  return (data) => {
    observer.next(data)
  }
}) 
//...
myObservable.subscribe()('someData')

但是,我确信有更优雅的方式。 任何想法?

3 个答案:

答案 0 :(得分:6)

观察对象的ES6方式是Proxies。您创建一个包装原始对象并在其上完成工作的代理。您可以使用它来创建类似于Observable.ofObjectChanges的内容。这是部分实施(仅set。您需要实施其他traps):

Observable.ofProxyChanges = (target) => {
  let subject = new Subject
  let proxy = new Proxy(target, {
    set(target, key, val) {
      let oldValue = target[key]
      target[key] = val
      subject.next({
        type: oldValue === undefined ? "add" : "change",
        object: target,
        name: key,
        oldValue: oldValue
      })
    }
  })
  return [proxy, subject.asObservable()]
}

let [obj, objChange$] = Observable.ofProxyChanges({})
objChange$.subscribe(console.log)

obj.bar = 1 // logs { type: "add", name: "bar", object: { bar: 1 } }
obj.foo = 2 // logs { type: "add", name: "foo", object: { bar: 1, foo: 2 } }
obj.foo = 3 // logs { type: "change", name: "foo", object: { bar: 1, foo: 3 }, oldValue: 2 }

答案 1 :(得分:3)

我建议使用类似于redux方法的东西,当对象的更改可以以预定义的方式进行:

function factory(reducerByType, initialState) {
  const action$ = new Rx.Subject();
  const state$ = action$
    .startWith(initialState)
    .scan((state, action) => {
      if (reducerByType.hasOwnProperty(action.type)) {
        return reducerByType[action.type](state, action);
      }
      
      return state;
    })
    .distinctUntilChanged();
  
  
  return {
    action$,
    state$,
    dispatch: action => action$.next(action)
  }
}

const {state$, dispatch} = factory({
  ADD: (state, action) =>  state + action.number,
  SUBTRACT: (state, action) =>  state - action.number,
}, 0);

state$.subscribe(val => console.log(val));

dispatch({
  type: 'ADD',
  number: 10,
});

dispatch({
  type: 'SUBTRACT',
  number: 15,
});

dispatch({
  type: 'SUBTRACT',
  number: 0,
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.0/Rx.js"></script>

答案 2 :(得分:-1)