Reputation: 581
Is there any RxJS function that could help me to get a subset of an array with the changed objects?
Something like distinctUntilChanged
but that I would return me an array with the changed objects instead of all the objects?
An example of my environment would be:
this.store.select(mySelector) -> observable for a list of objects
I want to pipe my observable that is getting updated almost every 100ms to return me only the updated objects instead of the full list. I have been thinking about the best solution for this since the performance will matter in this case but I can't think of anything, anyone got any suggestions?
Edit: I thought about doing a distinctUntilChanged
and assign the prev and current array to variables and then work with those variables on a map
but it doesn't seem the best option neither that it will have a good performance.
Solution: I got to a solution by mixing @MoxxiManagarm answer with this one How can I get which object changed in a BehaviourSubject in RxJs? and the result was something like:
myComparator = (prev: any, curr: any) => {
const returningValue = [];
curr.forEach((obj) => {
const prevObj = prev.find((v) => v.id === obj.id);
if (!prevObj) {
returningValue.push(obj);
} else {
if (JSON.stringify(prevObj) !== JSON.stringify(obj)) {
returningValue.push(obj);
}
}
});
return returningValue;
}
this.obs$ = this.store
.select(mySelector)
.pipe(
startWith([]),
pairwise(),
map(([prev, curr]) => this.myComparator(prev, curr))
);
Upvotes: 2
Views: 1100
Reputation: 9124
You could use pairwise and a function who compares both emitions. In my example I used lodash's without.
const data = of(
['A'],
['A', 'B'],
['A', 'B'],
['AA', 'B'],
);
data.pipe(
startWith([]),
pairwise(),
map(([l, r]) => without(r, ...l)),
).subscribe(console.log);
Output:
["A"]
["B"]
[]
["AA"]
Stackblitz: https://stackblitz.com/edit/rxjs-wn9rxy?file=index.ts
Upvotes: 2