I have a complex object having child objects and arrays and so on.
I can easily create a Subject/BehaviourSubject or Observable from this object so that I can "next" (emit) the new state to the subscribers.
[ex: let appEnv$ = new Rx.BehaviorSubject<IWebSocketAppEnv>(appEnv);
]
However I don't want all my subscribers to be notified every time the object changes. For instance for one of my subscriber, I only want to be notified when a change occurs on an elements of an array of that object.
Actually what I want is something redux is already doing. In redux, I can subscribe to the store but selecting only a child element.
I want to implement the same infrastructure for my back-end websocket server application.
How can I achieve that with RxJS?
Use distinctUntilChanged operator. (docs)
Let's assume that the object's structure is:
{
articleId: 0,
comments: [ 'lorem', 'ipsum' ]
}
We want to be as cool as firebase guys so we'll update comments in real-time when the updated object has a different array.
I'm using RxJS5
for observables and lodash
to compare arrays because operator's default behavior won't compare them in the way we want them to be compared.
// Our BehaviorSubject which emits new object.
// For those who don't know: it'll emit the latest emitted value when subscribing to it.
const object$ = new Rx.BehaviorSubject({
articleId: 0,
comments: [],
});
// If you want specific parts of your application
// to react only when a specific part of the object has changed, you
// have to create another observable using 'map' and
// 'distinctUntilChanged' operator and subscribe to it.
const comments$ = object$
.map(object => object.comments) // we want to emit comments only
.distinctUntilChanged((a, b) => _.isEqual(a, b)); // emit only when currently emitted value is different than previous one.
comments$.subscribe(v => console.log(v)); // log fresh comments
object$.next({
articleId: 1,
comments: [],
});
object$.next({
articleId: 1,
comments: ['lorem', 'ipsum'],
});
object$.next({
articleId: 2,
comments: ['lorem', 'ipsum'],
});
object$.next({
articleId: 2,
comments: ['lorem', 'ipsum', 'dolor', 'sit', 'amet'],
});
effect:
[]
["lorem", "ipsum"]
["lorem", "ipsum", "dolor", "sit", "amet"]
effect without distinctUntilChanged
operator:
[]
[]
["lorem", "ipsum"]
["lorem", "ipsum"]
["lorem", "ipsum", "dolor", "sit", "amet"]
JSFiddle
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