Closed mikl closed 13 years ago
Hi mikl,
I would suggest calling a server function from the client in a now.ready(function(){ })
block. Variable changes outside of now.ready (like your use of now.user) are synced upon server connection being established, and thus calling a server function in the now.ready block (which runs after connection is fully established should guarantee that the function is called when client data has synced
I've found the connect handler to be not so useful as it's not possible to set anything to now before the hander is triggered.
Similarly, I get problems with client-side code like this:
now.something = "x";
now.proof();
and server code like this:
everyone.now.proof() { console.log(this.now.something) }
it prints undefined - even if inside now.ready.
with client side code like so:
now.something = "x";
setTimeout(function() { now.proof(); }, 1000);
It works as you'd expect.
This may be a more pronounced problem with increased network latency - for example in local development these problems may not materialize at all - and then you deploy and things intermittently don't work correctly - which is my experience.
It would seem that now should not process/not send method calls if it can determine it is not in a synced state - or some other such solution whereby users can modify the now object on the client and expect their next call to guarentee their modifications are present on the server now object by the time the code is executed.
Right. Assigning to a now's key looks like a sync operation, but it isn't. And setter syntax doesn't allow to use simple continuation style.
Below is how I'd personally like to see it: now.set({something: 'x', whatever: {deep: {level: {you: 'like'}}}}, function() { console.log('something is set'); now.proof(); })
. We'd have then to decide should now#set
be a local predefined function, or instead a real remote caller (which obeys fully NowJS way).
Setters being given up, we can remove dependencies and support whatever browsers socket.io support w/o any additional shim.
update: plus, now#set
would allow to batch changes, which is virtue
@dvv: What makes it worse is that the function calls are (somewhat) synchronous, so the statements might actually take place in reverse order as in @AD7six’ example.
@dvv for syntax I'd prefer something polymorphic allowing any of
now.set("key", "value", cb);
now.set({"key": "value"}, cb);
now.set({"key": "value", "nested.key.no.wallop": "value"}, cb);
Perhaps if exposed the current setter logic could be kept allowing users to choose. now.key = "val"
is pretty convenient, just seemingly not always appropriate
Well, I guess now.key = "val"
could compile down to now.set({key: "val"})
which should be equivalent to now.set({key: "val"}, undefined)
. This'd normalize things.
On other forms of call you showed: the first seems acceptable, the second is not, as it respawns the long-beared problem of people treating dots as delimiters. Dots are perfectly valid chars in object keys. Dot. ;)
@dvv it was in part to point out that using nested dictionaries creates ambiguity. I.e. Does whatever get merged or overwritten? how do you achieve both overwrite and merge with that syntax?
I would also introduce a deleting sugar: now.set({foo:{bar:null,baz:undefined}})
should delete now.foo.bar
and now.foo.baz
. Thus, the complete control of extending/shrinking NowJS context might be achieved with one simple function.
@AD7six: it always merges. If you want to overwrite a whole object, you should nullify it first. This is virtue since allows to free references and let gc turn its chainsaw on.
If it doesn't fit, it's easy to implement additional custom merge helpers. I'm sure you understand those are for advanced usage and users, which are supposed to implement them.
update: extended version now.set([{foo: null}, {foo:{bar:'baz'}}], cb)
can be used to batch the changes, which are to be applied sequentially
@AD7six
So the issue you mentioned occurs because of the lag time between new values being recognized and being. If now.something
had previously been defined and you merely change now.something
to a new value, it would be synced to the server before now.proof
is called. This is simply a limitation of getters/setters in ECMAScript.
How about this solution: What if upon a remote function call, if some nominal amount of time has passed since the last operation, run the loop that finds new properties and thus syncing them before the function call is sent down the pipe. This way you won't encounter weird issues of lines not appearing synchronous.
@dvv, @AD7six, @mikl,
In the latest 0.7 on('connect') and ready this issue has been completely resolved.
There is no longer the lag time between client side variable changes and variable syncing .
Everything is fixed =]
@ericz awesome, thanks :)
It would be very helpful if there was a pattern for the client signalling “ready to go” or something like that. I am building an app that suffers from sporadic runtime errors due to
on("connect")
firing before the data is synced from the client.On the client side, I have:
And on the server side, I have:
Sometimes, this code crashes the server due to this.now.user being undefined. An option here is to just do a
setTimeout
and check again half a second later, but that is inelegant and impractical.