如何使用 rxjs 5 观察对象变化
How to watch object changes with rxjs 5
我想监视一个对象,这样所有的订阅者都会被通知它的任何变化。
我已经看到了 ,
然而答案是无关紧要的,因为 RXjs 版本 5 不再包含 ofObjectChanges 在它的 API 中。
我看过一些 "hacks" 比如创建一个 return 函数的观察者:
let myObservable = new Observable((observer) => {
return (data) => {
observer.next(data)
}
})
//...
myObservable.subscribe()('someData')
不过,我相信还有更优雅的方法。
有什么想法吗?
我建议使用类似于 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>
您需要使用行为主体。 https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/subjects/behaviorsubject.md
ES6 观察对象的方式是 Proxies. You create a Proxy that wraps the original object and do your work on it. You can use it to create something similar to Observable.ofObjectChanges
. Here a partial implementation (only set
. You'd need to implement the other 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 }
我想监视一个对象,这样所有的订阅者都会被通知它的任何变化。
我已经看到了
我看过一些 "hacks" 比如创建一个 return 函数的观察者:
let myObservable = new Observable((observer) => {
return (data) => {
observer.next(data)
}
})
//...
myObservable.subscribe()('someData')
不过,我相信还有更优雅的方法。 有什么想法吗?
我建议使用类似于 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>
您需要使用行为主体。 https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/subjects/behaviorsubject.md
ES6 观察对象的方式是 Proxies. You create a Proxy that wraps the original object and do your work on it. You can use it to create something similar to Observable.ofObjectChanges
. Here a partial implementation (only set
. You'd need to implement the other 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 }