[thelist] AJAX: Generlizating Response Handling, RFC

Matt Warden mwarden at gmail.com
Sat May 14 14:21:23 CDT 2005


evolters,

This is a request for comment on an idea I am trying to develop. I
would appreciate comments, criticisms, etc. even if there isn't an
associated solution/improvement. It's rather long, so my gratitude to
you if you read all the way through. As a note, you don't necessarily
have to be familiar with AJAX in order to comment, as it's more of a
general problem independent of AJAX. Further, I briefly explain the
problem below.

I am trying to create a general way to handle the XML responses from
an AJAX[0] situation. Recall that since it is asynchronous, if there
are multiple uses of AJAX, there could be multiple and different
requests dispatched and awaiting responses at any given time. So, it
is not sufficient to simply have one function that handles the
responses, and it is not even sufficient to change the response
handler based on the most recent request (because there could be
multiple responses incoming, of different types, and that require
different handling functions).

In an article[1] on xml.com, Drew McLellen suggests a solution that I
find significantly less than ideal. I quote:

"However, it is important that we keep these functions generic (we may
have multiple items on the page that need to make use of
XMLHttpRequest), and so hard-coding a reference to checkName at this
point would be foolhardy. Instead, a better design is to have the
server indicate the handling function as part of its response."

He suggests this as the response XML:

<?xml version="1.0" encoding="UTF-8" 
  standalone="yes"?>
<response>
  <method>checkName</method>
  <result>1</result>
</response>

The 'method' element indicates the Javascript function that should be
called to handle this result. So, this result would call checkName()
using eval(). I personally think this solution is somewhat ridiculous,
especially from a maintenance perspective, and especially if one uses
this method all over the place. If the Javascript function is ever
renamed, (a) the script will no longer work, which is expected, and
(b) the user will get a bunch of javascript errors, which is messy and
could be avoided easily.

My solution is to dispatch requests based on registration. For example:

function registerResponseHandler(String elementName, Function handler);

Where elementName is the name of the element in the response that
should be forwarded to the function defined by handler.

So, typical calls to register a response handler would be like so:

registerResponseHandler('username', handleUsername);
registerResponseHandler('chatmessages', handleMessages);
registerResponseHandler('chatuserlist', handleUserList);

where handleUsername, handleMessages, and handleUserList are
Javascript functions. This would alter a hashtable that looked like
so:

regRespHandlers = {
    'username' => handleUsername,
    'chatmessage' => handleMessage,
    'chatuserlist' => handleUserlist
}

Then, when the response comes in, it is dispatched accordingly, based
on the elements in the response. Consider two responses:

<?xml version="1.0" encoding="UTF-8" 
  standalone="yes"?>
<username value="mwarden" available="false" />

Which indicates that the username 'mwarden' is already taken (please
reserve your quibbles about my XML semantics/structure -- only for
demonstration). The nodes of the XML response would then be looped
through FULLY and dispatched based on the element name. This response
contains only one element, 'username'. This XML element and all its
children would be passed to the appropriate handler, like so:

if (regRespHandlers[elementName])
{
    regRespHandlers[elementName](...);
}

In this case, regRespHandlers['username'](...);, which would call
handleUsername(...).

Now consider thsi response (using mostly attributes to save space in
this example):

<?xml version="1.0" encoding="UTF-8" 
  standalone="yes"?>
<chatroom>
    <chatuserlist>
        <user name="mw" since="200505122456" />
        <user name="dj" since="200505111253" />
    </chatuserlist>
    <chatmessages>
        <chatmessage id="3" user="mw" value="I hate the AJAX acronym" />
        <chatmessage id="4" user="dj" value="me too" />
    </chatmessages>
    <foo>
        <bar>2576</bar>
    </foo>
</chatroom>

The dispatcher would traverse all element nodes and execute the same
code on each element node:

if (regRespHandlers[elementName])
{
    regRespHandlers[elementName](...);
}

This would send the entire chatuserlist node (including its children
to handleUserlist for processing. Likewise, it would send each of the
chatmessage nodes to handleMessages. However, elements chatroom, user,
chatmessages, foo, and bar do not have registered handlers, so they do
not get passed anywhere, except possibly as children of a parent node
with a handler.

My thinking is that this completely avoids the entire problem
introduced by the threaded nature of requests, as it takes out all
assumptions that are based on timing.

Can you see any potential problems with this method? What about
improvements or alternative methods? Surely this type of thing has
come up in typical threaded programming -- are there design patterns
from that area that you think might apply better?

Thanks for your help.

[0] http://en.wikipedia.org/wiki/AJAX
[1] http://www.xml.com/pub/a/2005/02/09/xml-http-request.html

-- 
Matt Warden
Miami University
Oxford, OH, USA
http://mattwarden.com


This email proudly and graciously contributes to entropy.


More information about the thelist mailing list