Comments (8)
Interesting! I'm using node. Wonder why it would be platform specific. Different Proxy implementations?
from observer-util.
Hi!
This is normal, but you probably want to do something different.
By default reactions are executed synchronously on observable mutations. This usually results in reactions running a lot of times for complex mutations.
There is a lot going on when you do list.push('World!')
. list.length
, list[1]
and a hidden key for object enumeration changes. console.log(list)
uses list.length
and the hidden enumeration key to do its work so it updates twice (on each of the two key mutations). This will just get worse with more complex functions. I don't know your use case, but I am pretty sure that you don't want to run reactions synchronously on observable mutations.
You can pass a scheduler to observe. In this case the triggered reaction is not executed synchronously on observable mutations, but passed to the scheduler function instead. Take a look at this example:
import { observe, observable } from '@nx-js/observer-util'
import { Queue, priorities } from '@nx-js/queue-util'
const list = observable(['Hello'])
const scheduler = new Queue(priorities.LOW)
observe(() => console.log(list), { scheduler })
// this passes the reaction to the scheduler
// the scheduler logs ['Hello', 'World!'] once when the browser/Node has some free time
list.push('World!')
Typically a scheduler does two things:
- It defers the works based on the passed
priority
. - It removes duplicate reactions.
You can use custom schedulers, but I advise you to use the @nx-js/queue-util. You can learn more about schedulers in this docs section, be sure the check all three examples.
I hope this helped 🙂
Edit: By using a bunch of schedulers with different priorities, you can implement something similar to React Fiber
Edit2: A debugger option is under development for observe
, which gives you an exact reason for every reaction trigger. It shows you which observable property mutation scheduled the reaction and where does the reaction uses the specific observable property.
from observer-util.
@lukeburns can I close this?
from observer-util.
Yep! Thanks for the helpful explanation, and the update on the debug option under development.
from observer-util.
I tweaked this behavior a bit in v4.1.0. From now on any atomic operation is guaranteed to schedule a reaction maximum once. By atomic operation I mean a JS operation, which is implemented in none interceptable native code (like property get/set).
Also I added a new experimental debugger. The easiest way of trying it out is this:
let dummy
const person = observable({ name: 'Bob' })
observe(() => dummy = person.name, { debugger: console.log })
person.name = 'Rick'
This logs the context of every single operation that is related to the observed reaction. It will log that person.name is used with a get
operation in the reaction and that person.name
changed value later. From this stream of data you can deduce why The Observer Util decided to schedule the reaction. The debugger API is designed to be raw. It pushes out a lot of metadata, which meant to be aggregated and filtered by 3rd party libs for larger projects.
from observer-util.
Thanks for your work on this. This change certainly gives me the behavior I originally expected with the code above!
However, I'm receiving a Max call stack size exceeded
error with the dummy code you shared above.
Additionally,
const person = observable({ name: 'Bob' })
observe(() => console.log(person))
person.name = 'Rick'
only logs { name: 'Bob' }
, when I expect { name: 'Rick' }
to also be logged — as in version 4.0.
from observer-util.
What platform are you on? Did you get this result in NodeJS or the browser? (For me it seems to be only buggy in NodeJS).
from observer-util.
I fixed the first (infinite loop issue) in the 4.1.1 release. Thanks for catching the bug 🙂
The second issue is specific to the NodeJS console.log
implementation. Normal for in loops
and object enumeration works, but apparently NodeJS console.log is implemented in native code. It is not getting person.name
under the hood (you can see this with the now working debugger).
I will see if this can or should be fixed. Is this a big issue for you? I imagine this would only be used for debugging purposes.
Edit: instead of getting each property key, Node gets a shady inspect
prop for console.log. I guess Object.prototype has a custom inspect
prop in Node which points to some native magic.
from observer-util.
Related Issues (20)
- Mutating observables in reactions is forbidden HOT 2
- 4.2.0 broke something HOT 3
- Trap "toJSON" to allow serialization of proxies HOT 2
- Deeply observe object HOT 12
- Documentation suggestion HOT 2
- Is it possible to receive the type of change when observing a value? HOT 9
- Observables arrays don't appear to observe correctly HOT 3
- Question about scheduler batching and observe optimizations. HOT 2
- Problem when changing whole objects HOT 1
- Understanding reactions HOT 1
- Angular 7 Integration HOT 1
- Not sure I'm understanding this at all HOT 4
- Object.defineProperty should trigger reactions HOT 3
- computed properties no cache? HOT 3
- Observing through a Proxy HOT 2
- `construct` trap fails for observed constructors HOT 1
- Bug or user error? Copying observable to other position in array converts it to the raw item
- should observe explicit array length changes
- Shallow observing HOT 1
- rawToProxy WeakMap.set is never called
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from observer-util.