8

I am trying to detect changes in an array of objects using JavaScript proxies.

Problem: Any time there is a change in array like deletion or insertion, i want to get that deleted or inserted item.

Current Code

target = [{ id: 1, a: 'a' }, { id: 2, a: 'b' }];
proxy = new Proxy(target, {
    get: function (target, property: string, receiver) {
        if (property === 'pop') {
            console.log('deleted object', target[target.length - 1]);
        }
        console.log('get', property);
        // property is index in this case
        return target[property];
    },
    set: function (target, property, value, receiver) {
        console.log('set', property, 'to', value);
        target[property] = value;
        // you have to return true to accept the changes
        return true;
    }
});

Current Thoughts: I did a little workaround to get the deleted item from array but it only works for pop() method because it deletes the last item from array. But i need a way to get the changes even it is made using splice method or push or pop.

Thanks.

[Update] Solution I Found:

https://github.com/ElliotNB/observable-slim I used this library to detect changes in array, i am able to detect changes on nested properties inside array too. This is exactly what i was looking for.

The reason i am using this library is because it's using proxies.

Johar Zaman
  • 1,955
  • 17
  • 27
  • If you want to capture `splice`, then you'll have to write a handler for splice just like you did for `pop` - look at the arguments to see what will be deleted and then and store the data before it's deleted. Rinse and repeat for every method you want to handle. – caesay Feb 28 '19 at 11:05
  • I tried but i didn't get the splice arguments inside this proxy handler. – Johar Zaman Feb 28 '19 at 11:05
  • https://www.npmjs.com/package/underscore-observe There was this library to observe changes in the array but this is using Array.observe() which is now Obsolete. and proxies are alternative for Array.observe so there should be a way to detect these changes using proxies. – Johar Zaman Feb 28 '19 at 11:11
  • @JoharZaman is Proxy important to you ? or any other way will be fine also ? – shajji Feb 28 '19 at 11:12
  • You shouldn't be tracking method calls at all, you only should be tracking indexed elements. – Bergi Feb 28 '19 at 11:15
  • @shajji Actually i am observing changes in individual objects inside array using proxies so it will be good for me if i can detect array changes with proxies too. But if you have any other solution which solve my problem i will look into it and see if it can work for me or not. – Johar Zaman Feb 28 '19 at 11:15
  • @Bergi i have also tried to track index but when i use splice on proxyArray it is not returning the index of deleted item. I think because it have to rearrange the positions so it get all the indexes of array. – Johar Zaman Feb 28 '19 at 11:18
  • @JoharZaman Yes, you will need to track rearrangements as well, it's the only reliable way. Arrays aren't interacted with only through their methods. – Bergi Feb 28 '19 at 11:35

1 Answers1

0

I recommend not to expose actual traget on getter. You can create a wrapper function to support the cutosom modifier. Check out the below example.

const target = [
  { id: 1, a: "a" },
  { id: 2, a: "b" },
];
const proxy = new Proxy(target, {
  get: function (target, property, receiver) {
    switch (property) {
      case "push":
      case "pop":
      case "slice":
      case "splice":
        return (...arg) => target[property](...arg);
    }
    throw Error("Not supported yet");
  },
});

proxy.push({ id: 3, a: "c" })
console.log(proxy.pop())
console.log(proxy.slice(1,2))
console.log(proxy.pop())
xdeepakv
  • 7,835
  • 2
  • 22
  • 32