gullerya / object-observer

Object Observer functionality of JavaScript objects/arrays via native Proxy

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add "get" trap

dragonworx opened this issue · comments

Hi, great work on the library! I'm currently using it for another project but would really love the ability to enable a "get" trap for any deep getters triggered.

I imagine this would probably be best done as an option to .observe and turned off by default, as most people would be interested in setters. However by adding this trap you have even more ability with this library to observe deep object usage.

Would you consider adding this? I was considering forking it but of course being the author you would get this done faster and without chance of regression or bugs.

I also use TypeScript and have a definition file I made by hand.

declare module 'object-observer' {
   export interface Change {
      type: 'insert' | 'update' | 'delete' | 'shuffle' | 'reverse';
      path: Array<string | number>;
      value: any;
      oldValue: any;
      object: any;
   }

   export type ChangesHandler = (changes: Change[]) => void;

   export interface Options {
      path?: string;
      pathsOf?: string;
      pathsFrom?: string'
   }

   export class Observable {
      static from(obj: any): Observable;
      static isObservable(obj: any): boolean;
      observe(callback: ChangesHandler, options?: Options): void;
      unobserve(): void;
   }
}

Feel free to modify it, or submit it to @types/object-observer.

Thanks again!
Ali

Hi and thanks for the feedback!!

I'll take a look onto the PR for the 'get' observation early next week, sorry for the delay.
In general the only thing I'm somewhat concerned with is the possible performance effect, since having this trap in place will invoke the observers invokation flow regardless of the flag state, which is resolved further down the flow stream.

Can you please shortly:

  • describe some functional use case for this?
  • when a deep 'get' is performed are you interested in only the notification on the final node, or also all the nodes along the path

Hi thanks for the response!

Yes I would be interested to hear your thoughts and findings on the performance impact of these changes. I have not done any benchmarking (do you have any perf tests we could compare?).

Even though the callObservers function would be called more, it would filter out the changes if they are not enabled via the enableGet option, so while that flow is invoked more it is not necessarily calling the consumer more if not required. If you have consumers which update the DOM (like a view or display library) then that would probably be the heavier operations rather than the Proxy -> object-observer code.

My use case is that I am writing a React state management library, as I just can't stand living with reducers and actions (not saying they don't work, just saying the boilerplate is a pain). My ideal store would be a mutable global store where components can just make changes and all dependants of the data re-render. Not only do I need to know when the store (any any depth) is updated, but also when it's accessed during the component render, so that I auto-wire the dependancy of the component to the store data paths. So far my store is working nicely, but you have to manually declare during the component render what paths you wish to update on, so I am really trying hard to find a way to make that just implicit. Hence the need to know when some part of any object (in my case the store) is accessed, as I am listening for those changes only during a functional components render. I would still have the enableGet option on, I would just be ignoring any get changes if not during a component render.

In terms of a deep get as you mentioned, I would only be interested in the final node, though having the deep path info provided by the change's path array is super useful.'

Closing discussion, please reopen if the said above is missing / unsatisfying or new considerations available.