João Silva
João Silva

Reputation: 581

RxJS get only changed objects from array

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

Answers (1)

MoxxiManagarm
MoxxiManagarm

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

Related Questions