Closed saulshanabrook closed 9 years ago
Would i use the emitted events example?
controller.eventEmitter.on('change', onChange);
Would this call onChange
for every change in the tree?
I have not exposed the tree because then Cerebral will loose control of it. A change to your tree will always be done with a signal, so your signal knows about this update before the tree :-)
Do you have a bit more details on the use case? I can give you an example of how you would solve it with Cerebral.
Absolutely everything starts with a signal.
Really great that you ask these questions! :-)
I have a large part of my tree that is sent as JSON via websockets on every change. It is a very poor man's synchronization between clients. Just send the whole state to the server on every change, and then sound out the updated state to the other clients connected.
So I want to attach a listener to a part of the tree, so that every time any action updates it, it can be sent to the server.
So I guess I could add sendData
at the end of every signal. It just seems like a more verbose solution then how I am currently doing it with baobab.
Aha, I see!
Both your suggestions will work, though the first onChange
suggestion will always receive the whole tree. You could of course just store the branch of the tree in a variable and check if it has changed whenever there is an update.
But what you can do with Cerebral to really optimize this is share the signals, not the state. So when a signal triggers you send the argument passed to that signal and what signal was triggered over the wire. Then run that signal on the other client. A lot less data and more effective. Does that make sense?
So instead a "sendData" at the end, you have a "shareSignal" at the start.
controller.signal('somethingHappened', shareSignal, doSomething);
controller.signal('somethingElseHappened', shareSignal, doSomethingElse);
So with a "per signal" control you can effectively share and rerun them on other clients.
On your last suggestion, that does make sense and would work if I was just synchronizing clients, but I also parse the JSON on the server (in Go). And on the server, it needs to be able to parse the whole JSON tree in order to compute some things about it.
Aha, I see! Well, in your scenario I think this is the best solution:
var currentBranch = null;
controller.eventEmitter.on('change', function (tree) {
if (currentBranch !== tree.some.branch) {
currentBranch = tree.some.branch;
// AJAX stuff
}
});
I am making a lighting control dashboard, so multiple clients edit at the same time and changes are synced between and to the server.
Why would I want to share signals between clients? Can't I just share the state?
I am thinking about it like this. When a client gets an incoming websocket message, that contains an updated state. So it sends a signal 'incomingWebsocketMessage
. Which has a listener that will update the state with the incoming state.
Ah I see. Is it possible to get the old state for in that .on('change', function (tree)...
method? Also that tree
is the controller
thing right?
I just recorded my state each time, so I can compare if it has changed. The synced
part of the tree is the on that is (duh) synced.
var lastSynced = null
controller.eventEmitter.on('change', function (tree) {
const newSynced = tree.synced
if (newSynced !== lastSynced) {
Storage.store(tree.synced)
lastSynced = newSynced
}
})
Since the signals will run the same way on all clients it is just less data to send over the wire {signal: 'foo', args: {}}
. Then you run the signal when an update is received, using the little amount of information. This rather than sending a big object with lots of data where just a small thing actually changed.
But yeah, as you stated, you need the state change on the server too, so it will not work.
The controller is Cerebral, which internally uses the Baobab tree. Any mutations run inside actions will be not directly run on the tree, but proxied to the tree. Any 'change' events will have the tree passed to it.
So the tree is very much "hidden", because the idea is that you work with the "controller", not the "model". If that makes sense, just wrote an article about it :-)
http://www.christianalfoni.com/articles/2015_08_02_Why-we-are-doing-MVC-and-FLUX-wrong
Yeah, great! there it is! :D
@christianalfoni Just reading your article now. I have actually decided to add a shareData
across all signals that mutate data that needs to synced. The reason for that is previously I was using the commit
function in baobab, with autocommit: false
, to do a bunch of changes then sync them all at once. However, that isn't possible with cerebral, right?
So to get a similar effect, I can have a sync handler type thing that I add to be the last signal handler.
Actually I have to check that up with Baobab author. V2 of Baboab does all state updates synchronously, but when I tried to just pass the tree when the signal was done running, it did not have the updates. So now Cerebral runs a commit() before the change event is triggered.
So I think you might currently have to use your initial approach, but it should not be necessary though. Have asked author on https://github.com/Yomguithereal/baobab/issues/322
@christianalfoni thanks!
@christianalfoni How is it possible to get access to the commit
baobab function to create a commit
action like this? https://github.com/Yomguithereal/baobab/issues/322#issuecomment-127060364
I checked it up, there was an option that was not set. Now any mutation is instantly accessible and you can safely access the latest state on the latest action in a signal :-)
Version 0.2.1 released
This will be default when V2 is ready, as stated here:
" Syncwrite
The tree now write synchronously only but will continue firing its update events asynchronously for obvious performance reasons. "
@christianalfoni But is it possible to execute multiple actions then only commit after all of them have finished?
Baobab author is back from vacation now, so V2 is closing on release. I have to discuss it a bit more with him. There is some confusion in that you can do mutations and get changes, then commit all later... but they do not seem to be available when getting state using parent paths.
So yeah, need some more checkup, but this will work optimally when Baobab V2 is officially released :-)
Is it possible to achieve something similar to:
I want to be able to monitor one part of the tree for an update.