I want to detect changes to arbitrary objects, such that I can react to them. I have the ability to intercept their creation process, so essentially the boilerplate I have is something like this:
function withChangeDetector(factory) {
const obj = factory();
return attachChangeListener(obj, () => console.log("Change occurred");
}
const myObject = withChangeDetector(() => new MyObject());
doSomethingThatMayChangeMyObject(myObject);
// if ^ changes myObject at any point in the future, then we should see the "Change occurred" log line
The constraints that I have are:
- I do not control the factory method, i.e. it can create any arbitrary object.
- I do not control the
doSomethingThatMayChangeMyObject- i.e. anything may happen here. - I DO control the
wihChangeDetector/attachChangeListenerfunctions. - I can't use polling.
Now my first instinct is to use a proxy. Simplified, it would be something like this:
function attachChangeListener(obj, onChange) {
// I'm ignoring nesting here, that's solvable and out of scope for this question.
return new Proxy(obj, {
set: (target, key, val) => {
const res = Reflect.set(target, key, val);
onChange();
return res;
}
});
}
Now this works great for external changes to an object, but unfortunately it doesn't quite work for internal changes in class instances. The problem is that if the caller defines their class like this:
class MyObject {
prop;
setProp = (val) => this.prop = val;
}
then this will be bound to the unproxied instance, and therefore the proxy will not be called, and it won't detect the change.
Hooking into get and doing some magic there is also not going to work, as this won't detect async internal changes to MyObject (e.g. imagine setProp using a timeout).
Is there any way that I can detect changes to MyObject - using a proxy or otherwise - given the constraints I outlined above?