2

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))
        );
4
  • 1
    There is no rxjs operator that detects changes in arrays or objects. What you're asking for is an operation on two arrays. How to get the difference between two arrays in JavaScript? Can you give an example of what your observable emits and what should be emitted. Commented Aug 24, 2020 at 9:27
  • @fridoo it emits a list of objects that contains GPS coordinates and other properties, but to update it in an integration with google maps I want to update only the objects that changed, that's why I wanted to compare both previous and current array and then get only the changed objects. Commented Aug 24, 2020 at 10:09
  • Does this answer your question? How can I get which object changed in a BehaviourSubject in RxJs? Commented Aug 24, 2020 at 10:19
  • @fridoo I'm trying to implement that in a way to work with my array, I'll let you know later if I succeed, thank you Commented Aug 24, 2020 at 10:48

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

2 Comments

I can understand the logic of it but someone it's not working with my objects, I still receive my full array even when the objects didn't change between the updates.
Well, your solution gave me a good idea in how to mix it with the one in here: stackoverflow.com/q/1187518/9423231 To achieve my goal, I'll keep you updated if I could reach the solution I'll just mark it as an answer and update my question with my solution

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.