Giter VIP home page Giter VIP logo

Comments (9)

solkimicreb avatar solkimicreb commented on May 29, 2024

I missed this issue, sorry. Answer coming soon for this one and your other one.

from observer-util.

solkimicreb avatar solkimicreb commented on May 29, 2024

You can check the debugger option. This lib can react to a lot of different mutations and the debugger is called with some contextual data about each mutation. I think you should try it and see if it is what you need. If not, we can continue the discussion.

Implementing something very similar to mobx's observe could be done like this:

const obj = observable({})

// this calls `console.log` with some contextual data on every change at any depth of obj (because of JSON.stringify)
/// you can replace `console.log` with your own function to do something with the data
// or replace `JSON.stringify` for a more detailed observation.
observe(() => JSON.stringify(obj), { debugger: console.log })

from observer-util.

Dai696 avatar Dai696 commented on May 29, 2024

Oki great! I got the scheduler working but now I'm onto the debugger. I see that the debugger has a "add" and a "delete" that shows me which thing got added/deleted

The issue I have now is using that info in the actual reaction.

I don't think their is anyway to feed the debugger data into the original reaction.

My goal is to combine the debugger with the scheduler

to analyize the changed array data. Scheduler works fine now with just using critical priority which is great! but i wanna be able to use the debugger data within the schedueled reaction.

Do I just cache the command I need and then use that inside the reaction function?


My current test code...

const scheduler = new Queue(priorities.CRITICAL);
        this.observeArrayTest = observe(()=>Manager.mapInstances.light.length
            , {scheduler: scheduler, debugger: console.log});

If I can get this solved this will remove my need for the hacked caching stuff I use right now for my observable.

(Which is some really awful code, I'm hoping to simplfy this process by reading the added/deleted from the debugger...instead of checking myself)


My actual code right now. Excuse how messy it is.

const scheduler = new Queue(priorities.CRITICAL);
this.observerMarque = observe(()=> this.forceObjectMapChange(), {scheduler: scheduler})

$.forceObjectMapChange = function() {

        const cache = Object.assign([],raw(this.mapStoreCache));
        const current = Manager.mapInstances.light;
        const added = [];
        const removed = [];
        for (const i in current) {
            if (!cache[i] || current[i].ID !== cache[i].ID)
                added.push(current[i]);

        }
        for (const i in cache) {
            if (!current[i] || cache[i].ID !== current[i].ID) {
                removed.push(cache[i]);
            }
        }
       
        added.forEach((obj) => {
            this.addObject(obj);
        });

        removed.forEach((obj) => {
            this.removeObject(obj);
        });
        
        this.mapStoreCache = JSON.parse(JSON.stringify(raw(Manager.mapInstances))).light

    };

Thanks for ur amazing support btw!

from observer-util.

Dai696 avatar Dai696 commented on May 29, 2024

One other thing, I noticed some strange behavior with observable arrays (or an object) and setting a none observable to it.

I have a undo/redo store which I use to hold a stack record of changes.

I experimented setting my observable map instance array to equal a none observable version of itself from the history stack when undoing.

I'd add an object to my scene... (this pushes an observable object into the map instance store.

Then I'd save a snapshot (which is just a regular object version of the instance store saved in the history store stack)

Then I'd delete the object I placed in the map.

Then call undo, setting the observable instance store to the regular instance store saved in the history stack .

It'd run the observe that reads the instance store array and update the map based on added/remove d objects (undoing the deletion of the object)

(The observable is the last function in my previous post before this one)


However... that same observe I set doesn't work properly anymore after that. It won't fire if I add new items to the array. So I thought somehow the observe connection was lost due to me setting the observable array to a regular array.

Strangely if I delete stuff the observe works... and it works if I add more snapshots to the history... and undo with that new snapshot...

For example if I add a bunch of objects (the observe wont fire) but if I save a snapshot... add more objects (observe still doesn't fire) then redo... (the observe suddenly fires)

When I checked if the observable array was still a observable, it said it was....

I'm really confused at this behavior... It wont allow the observable to update when pushing to it... but it will update when removing from it... (so splicing)

I'd really love if u could help me figure this one out...

This is really odd behavior to me... even if I did a lot of things wrong... I'm not sure it should be acting this way


Below i posted most relevant code... I apologize for being spammy.

I'm so close to fixing this and I feel like you could help me out.

Thank you again so much for ur help so far!


Ex of my history code that creates this behavior

 addSnapshot(store = this.mapInstances, config) {
            this.historyStore.stack.push(JSON.parse(JSON.stringify(store)))
            this.historyStore.index = this.historyStore.stack.length-1
        }

        get stack() {
            return this.historyStore.stack;
        }

        undo() {
            this.mapInstances.light = this.historyStore.stack[this.historyStore.index].light
        }

this.mapInstances is just a getter to the map stores current map data

     get mapInstances() {
            if (this.mapStore.currentMap === -1) return [];
            return this.mapStore.map[this.mapStore.currentMap]

        }

my map store

import uniqid from 'uniqid'
import {store} from 'react-easy-state'
import { observable, observe, isObservable } from '@nx-js/observer-util';
//console.log(observable)

const mapStore = store({
    currentMap: observable(0),
    map: observable([
        observable({
            light: observable([]),
            sprites: observable([]),
            collisions: observable([]),
            shadowCasters: observable([]),
            particles: observable([]),
            events: observable([])
        })
    ]),
    selectedMapInstances: observable([])


});

//console.log(isObservable(mapStore.map[0].light))
//observe(()=> console.log(mapStore.map[0].light.length))
export default mapStore

my history store

import {store} from 'react-easy-state'

const historyStore = store({
    index: -1,
    stack: []
});

export default historyStore

my add and remove objects code

       addMapObject(mode, obj) {
            this.mapInstances[mode].push(obj); // add object
        }

        removeMapObject(obj) {
            const argumentsLength = arguments.length;
            if (argumentsLength > 1) {

                for (let i = 0; i < argumentsLength; ++i) {
                    this.removeMapObject(arguments[0]);

                }
            } else {
                const {type} = obj;//gets object type

                const index = this.mapInstances[type].map(function (x) {
                    return x.ID;
                }).indexOf(obj.ID);
                this.mapInstances[type].splice(index, 1);
            }
        }

from observer-util.

Dai696 avatar Dai696 commented on May 29, 2024

Oki I got most of what I needed working, however I was curious if their was a way to combine the debugger with the scheduler.

Only way I found out how so far was to cache the debugger data, and then access that inside the observe or queue functions. Is this the intended way?

Also it a bit strange that the first function in the observe checks if the observable should be fired, but the scheduler doesn't. However it does have function support if you use a queue.

Is the intended behavior to just have the first observable function check if the observe should even happen, then use the queue schedulers functions to fire on observe?

Or just use the first function to observe and fire reactions?

Or is either fine... its just context that matters.

from observer-util.

solkimicreb avatar solkimicreb commented on May 29, 2024

I think I mislead you a bit with the debugger tip. It is really not meant to do what you are doing, it's just a utility to debug complex reaction chains. A mobx observe like functionality can be implemented fairly simple on top of observer-util. (This is why it is not part of the lib, I try to keep it low level.)

import { observe, unobserve, observable } from '@nx-js/observer-util'

// you can add a scheduler too, if you would like one
function myObserve (obj, prop, cb ) {
  let oldValue = obj[prop]
  return observe(() => {
     const newValue = obj[prop]
     cb(obj, prop, newValue, oldValue)
     oldValue = newValue
  })
}

const person = observable({
  name: 'Bob',
  age: 100
})

// this will be called when person.name changes
const reaction = myObserve(person, 'name', (obj, prop, value, oldValue) => {
  // do something based on old and new value here
})

// you can unobserve it any time
unobserve(reaction)

Arrays are a bit more complex since they have complex compound mutations. You could do domething like:

import { observe, unobserve, observable } from '@nx-js/observer-util'

// in case of arrays I definitely recommend a scheduler
// otherwise the observed function could fire a lot of times for compound mutations (like splice)
function observeArray (array, cb) {
  let oldArray = Array.from(array)
  return observe(() => {
     // maybe create some more digestiable data from array and oldArray
     cb(array, oldArray)
     oldArray = Array.from(array)
  }, { scheduler: yourPreferredScheduler })
}

const nums = observable([1, 2, 3, 4])

// this will be called when person.name changes
const reaction = myObserve(nums, (nums, oldNums) => {
  // do something based on the old and new array
})

// you can unobserve it any time
unobserve(reaction)

If you need a more digestible diff format you could add some array diffing to the observeArray function. There plenty of packages out there for that, maybe check this one.

Does this help? Are you looking for a more complex observe functionality? Are you interested in the scheduler addition?

from observer-util.

Dai696 avatar Dai696 commented on May 29, 2024

Thank you so much for the detailed response! I think this is what I'm aiming for!

As long as I can monitor the array changes and not have to compare entire arrays with new ones I'm happy.

Just being able to observe pushed data and sliced data is what I'm looking for in the array.

That way if I add items to the map, I can react to those added. If I removed I can also react.

How would you go about just observing if something was added or removed to the array (without needing to check an old one and compare the values?)

Edit*

I was reading this article on observable arrays
https://stackoverflow.com/questions/5100376/how-to-watch-for-array-changes

The 3rd method talks about using proxies, so I was thinking it may be possible already natively to observe specific method changes

I mostly just wanna see if the array slice or pushes, but pop, shift, unshift, ect... would be nice too.

Is this easily possible?

from observer-util.

Dai696 avatar Dai696 commented on May 29, 2024

Oh wow I'm slow, I didn't notice you provided info for differing arrays.

Ill take a look and see what I can do... Thank you!

from observer-util.

Dai696 avatar Dai696 commented on May 29, 2024

Awesome I got this working with fast-array-diff!

Thank you so much for your help!!

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.