Ajax in Action. Chapter 6: The User Experience | 3
Ajax in Action. Chapter 6: The User Experience
6.2.2 Handling updates from other users
Our planetary viewer application allows more than one user to log in at once, so presumably other users may be editing data while we are. Each user would presumably like to be informed of changes made by other users more or less as they happen. Most Ajax applications will involve more than one browser sharing a domain model, so this is again a fairly common requirement.
We can modify our XML response, and the Command queue object, to cope with this situation in the following way. For each update to the server-side model, we generate a timestamp. We modify the server-side process that handles updates to also check the domain model for recent updates by other users, and attach them to the response document, which might now look like this:
<command> tags, which are identified by the
ID of the Command object in the sent queue, there is an
tag, which in this case denotes that the distance from the sun of Venus has
been set to a value of 0.76 by another user called Jim. We have also added an
attribute to the top-level tag, the purpose of which we explain shortly.
Previously, our command queue sent requests to the server only if there were commands queued up. We would need to modify it now to poll the server even if the queue were empty, in order to receive updates. Implementing this touches upon the code in several places. Listing 6.1 shows the revised CommandQueue object, with the changes in bold.
We’ve added quite a bit of new functionality here. Let’s step through
it. First, we’ve introduced a global lookup of command queue objects .
This is a necessary evil given the limitations of the
which we’ll discuss shortly. The constructor takes a unique ID as an argument
and registers itself
with this lookup under this key.
The CommandQueue constructor now takes two other new arguments .
onUpdate is a Function object that is used to handle the
tags that we introduced into our response XML.
freq is a numerical
value indicating the number of seconds between polling the server for updates.
If it is set, then the constructor initializes a call to the repeat() function
setInterval() method to regularly execute a piece of code.
and its cousin
setTimeout() accept only strings as arguments
under Internet Explorer, so passing variable references directly into the code
to be executed is not possible. We use the global lookup variable and the unique
ID of this queue to develop a workaround to this problem in the
method. We also keep a reference to the repeating interval, so that we can stop
clearInterval() in our
fireRequest() method, we previously exited directly if
the queue of commands to send was empty. That test has been modified now so
that if an
onUpdate handler is set, we will proceed anyway and
send an empty queue in order to fetch any
<update> tags waiting
for us. Alongside our own edited data, we send a timestamp telling the server
the date that we last received updates ,
so that it can work out to send us relevant updates. This is stored as a property
of the command queue and set to 0 initially.
We pass these timestamps as UNIX-style dates, that is, the number of milliseconds elapsed since January 1, 1970. The choice of timestamp is based on portability. If we chose a date format that was easier to read, we would run into issues with localization, differences in default formats across platforms and languages, and so on. Getting localization right is an important topic for Ajax applications, since the application will be exposed to users worldwide if it is on the public Internet or the WAN of a large organization.
onload() function, we add the code required to update
the last updated timestamp when a response comes in
and to parse
<update> tags .
The onUpdate handler function is called with the command queue as its context
object and the
<update> tag DOM element as the sole argument.
In the case of our domain model of the solar system, the update handler function is shown in listing 6.2.
We’ve added quite a bit more clever code to our command queue object
in the process of handling updates from other users, including passing timestamps
between the client and web tiers, and adding a pluggable update handler function.
Eventually we come full circle to the issue of informing the user of changes
and asynchronous updates as they take place. In the next section, we look at
our options for presenting this information to the user in a more workable fashion,
and we’ll factor out that pesky
Written by Dave Crane and Eric Pascarello with Darren James and reproduced from "Ajax in Action" by permission of Manning Publications Co. ISBN 1932394613, Copyright 2005. All rights reserved. See http://www.manning.com for more information.
Created: March 27, 2003
Revised: October 31, 2005