【问题标题】:How to watch object changes with rxjs 5如何使用 rxjs 5 观察对象变化
【发布时间】:2017-11-06 06:04:42
【问题描述】:

我想监视一个对象,因此所有订阅者都会被通知它的任何更改。

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

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

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

但是,我相信还有更优雅的方法。 有什么想法吗?

【问题讨论】:

  • 我对这个问题的公认答案很感兴趣
  • 还没试过,但我相信@Skeptor 的回答对我来说会很有用。

标签: javascript rxjs rxjs5


【解决方案1】:

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 }

【讨论】:

    【解决方案2】:
    【解决方案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>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-17
      • 2018-09-15
      • 2018-10-25
      • 2017-03-31
      • 2022-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多