Giter VIP home page Giter VIP logo

Comments (18)

solkimicreb avatar solkimicreb commented on May 28, 2024 1

Just to clarify: instead of binding on observable properties once, nx-observe looks for yet unregistered parts of the function (hidden by conditionals or loops) on every run and binds on the newly revealed properties.

from observer-util.

solkimicreb avatar solkimicreb commented on May 28, 2024 1

Going to also add some basic benchmarks (nx-observe vs vanilla js for now). I guess it might be interesting for you too. (Right now I only have benchmarks for the whole nx-framework together)

from observer-util.

solkimicreb avatar solkimicreb commented on May 28, 2024

This is intended.
The observer callback reruns every time a property (nested or not) of any observable used by it changes. observe(() => console.log(observable)) doesn't use any property of the observable so it won't rerun on any change.

Try observer.observe(() => console.log(JSON.stringify(observable))), it will make it run twice too. The reason is that JSON.stringify() actually recursively gets all the properties, so the observer callback uses them all now.

I will soon improve the docs to give a better explanation.
Thx, for the comment (:

(Was there an actual use case where the above feature would be needed or did you just play around with the code?)

from observer-util.

SukantGujar avatar SukantGujar commented on May 28, 2024

My two cents... This exact issue made me move on from MobX for my React app. In my case it impacted render method, however the issue affects any conditional code... Consider a callback like this -
() => (observable.visible) ? observable.value : null
Depending on the value of visible, the access for value may not be invoked when this method is first executed. These conditionals are ubiquitous in React render methods.

from observer-util.

solkimicreb avatar solkimicreb commented on May 28, 2024

The example you provided works fine with nx-observe. It does something what I call 'progressive discovery'. When observable.visible changes value to true, the function is triggered and nx-observe registers a listener for observable.value.

However () => nonObservable.toggle ? observable.value : null would not work, as changing a nonObservable prop does not trigger the function for progressive discovery. I will document this as an edge case I think.

from observer-util.

SukantGujar avatar SukantGujar commented on May 28, 2024

So in the example I quoted, after the first run, if value changes, would the callback be invoked? Note that visible remains same across both runs.
Update:
In this example, the outcome of the function doesn't change between both the runs. I guess its not an issue as nx-observe will dynamically trap value when it's being referenced in subsequent runs.

from observer-util.

solkimicreb avatar solkimicreb commented on May 28, 2024

You pretty much summarized it in your update. Properties are always registered when needed (meaning when the function reveals a new part of itself.)

from observer-util.

SukantGujar avatar SukantGujar commented on May 28, 2024

Completely out of topic... I am working on creating an observable relational object model and I am thinking of extending on nx-observe. I need to store more metadata on every object, e.g. errors, model schema etc. and I need your opinion on extending this library.
I plan to use Symbol properties to store error and schema metadata alongside every observable field (a field is merely an observable object instance, containing value, error and schema of the object). This allows for easy coexistence of data and metadata. Do you see any immediate issues with this blend of Symbols and Proxy?

PS: Didn't want to re-purpose this for an off-topic discussion, but I didn't know of a slack channel to reach out.

from observer-util.

solkimicreb avatar solkimicreb commented on May 28, 2024

nx-observe does not bind on Symbol keyed properties at the moment, for the very reason you mentioned here. They tend to contain meta-information that is better left unobserved. It also doesn't bind on function valued properties. This line is the responsible for the behavior: https://github.com/RisingStack/nx-observe/blob/master/observer.js#L63. If you remove the conditions everything will be observed.

So symbols are safe to use, but WeakMaps are a more elegant solution for adding metadata to Proxy wrapped objects in my opinion, since they totally avoid the Proxy. In case you are not familiar with them, WeakMaps are documented here.

Another issue with symbols is that they are simple keys, meaning accessing and setting symbol keyed properties might walk the prototype chain. If you plan to to add metadata to the object and the object only I suggest WeakMaps. If the prototype chain walking is needed for you, go with symbols.

I made a gitter channel for nx-observe, but we con continue the conversation here too.

I am glad you plan to extend nx-observe (: If you have any questions about Proxies feel free to ask.

from observer-util.

SukantGujar avatar SukantGujar commented on May 28, 2024

Thank you for taking the time to address my questions :). I am delighted to have your opinion on the design.

Let me explain how the object store is implemented at the moment. It is an ImmutableJS based structure. Models are defined using a JSON schema like json definition. There is an underlying type system which handles core types like string, date, currency, number, object, array etc. Then user can use these core-types and customize their properties to create more types. The ORM store has field methods, e.g. set(path, value, schema) to add a plain vanilla JSON object value to the store on the given path. The schema is used to parse the plain JSON object into an Immutable field along with type checking and validations. As I mentioned earlier, every element in ORM is a field with three important properties- value, schema and error. This way every field in the tree holds all the information required to evaluate it. The schema evaluation methods are not part of this tree, they sit in a different library. All they need is the json schema to validate the field and update its error.

Now onto Weakmaps... As a lot of fields would share the same schema, I think this would create a lot of duplicate weakmap objects. Right now we have schema as a memoized function which allows a single instance being shared across all fields which belong to the same schema. Does this make sense?

I don't think we need prototype walking on the object because they are simple Immutable objects, not complex instances created from a class hierarchy.

Lastly, I certainly would want to observe error field changes, if not schema changes because that information drives error messages in the UI.

from observer-util.

solkimicreb avatar solkimicreb commented on May 28, 2024

Is your project open-source?

from observer-util.

SukantGujar avatar SukantGujar commented on May 28, 2024

Not at the moment...

from observer-util.

solkimicreb avatar solkimicreb commented on May 28, 2024

Sorry I am a bit lost 😄 A little example snippet of the desired result program interface would be really great.

I think I will change the 'do not observe symbols' thing to 'do not observe well-known symbols'. For selective observation you can use observable.$raw as documented here. With this you can control which fields trigger observer functions (like error) and which fields don't (like schema).

About WeakMaps I suggested to create a single WeakMap called meta. And use it like this:
meta.set(field, {schema, otherMeta, etc}). I am pretty sure I did not understand what you were saying here though 😄. Why do you use a memoized function instead of simply a reference to the schema object? (is it not an object under the hood?)

from observer-util.

SukantGujar avatar SukantGujar commented on May 28, 2024

Ouch, hope I didn't confuse you too much 😞. I will try to share a snippet. Basically, our ORM is a tree composed of objects which we call Fields. A field has these three properties -

  1. schema: Keeps the desired schema of this field handy.
  2. value: Stores the value of this field.
  3. error: If not null, it indicates any validation errors encountered by the type handling system when it validated this field's value as per its schema. Type handlers validate when there is a need to save a field in DB.
    An example string field looks like -
"UserName": {
    "error" : null,
    "schema" : {
         "type" : "string",
         "required" : "true"
    },
    "value" : "Albert"
}

As there will be tons of fields with same schema, the schema field is actually a memoized snapshot function, something like -

// memoized: a -> () -> a
schema : memoized( {
         "type" : "string",
         "required" : "true"
    })

So now all fields with same schema have the same instance of schema function which always returns a single schema json 😄 .

So using one weakmap with one entry per field will still not share schema, will it?

Your other feedback on observing the error Symbol is exactly what I needed, thanks!

from observer-util.

solkimicreb avatar solkimicreb commented on May 28, 2024

It is getting clearer, thx (: I will replace the no symbol, no function restriction with a no well-known symbol restriction, but before that I will have to run some benchmarks. (I try to keep nx-observe speedy). I will let you now when it is ready (hopefully this evening).

from observer-util.

SukantGujar avatar SukantGujar commented on May 28, 2024

Awesome, thanks!

PS; Found you on Twitter.

from observer-util.

solkimicreb avatar solkimicreb commented on May 28, 2024

I released the new version.

From v2.0.3 and upwards nx-observe observes everything except well-known symbols (normal symbols are observed.) Related commit is here.

I also added a rough benchmark, comparing nx-observe, MobX and vanilla JS. It is here.

Have a nice day (:

from observer-util.

SukantGujar avatar SukantGujar commented on May 28, 2024

Awesome, can't wait to try this. Thanks!

from observer-util.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.