I would like to watch over an object, so all the subscribers will be informed for any changes of it.
I saw it already been asked before, yet the answer is irrelevant since RXjs verion 5 do not include the ofObjectChanges in it's API anymore.
I've looked at some "hacks" like creating an observer which return a function:
let myObservable = new Observable((observer) => {
return (data) => {
observer.next(data)
}
})
//...
myObservable.subscribe()('someData')
However, I'm sure there is more elegant way of doing it. Any Ideas?
The following is an example of a typical Observer object: To use the Observer, provide it to the subscribe of an Observable: Observers are just objects with three callbacks, one for each type of notification that an Observable may deliver. Observers in RxJS may also be partial.
RxJS also offers takeWhile (), which allows you to take values until some boolean test holds true. We can write the above stream with takeWhile () like this: Aside from the fact that they work on Observables, not arrays, these functions are almost identical the familiar list operations.
update () takes care of updating the UI to reflect what we got from the server. Handling debounce, retry, and “distinct until changed” logic in an imperative, callback-based style is valid, but it can be both brittle and complicated. The takeaway is that programming with RxJS allows for:
Note: This article presupposes familiarity with the basics of RxJS, as presented in the article Introduction to Functional Reactive Programming with RxJS. Reactive programming is a programming paradigm that treats streams of data, called Observables, as its basic units of programming.
The ES6 way of observing an object is with 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 }
I would suggest using something similar to redux approach, when changes to the object can be made in predefined way:
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With