RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Generalized AJAX Response Handling for XML Content : Page 2

Making multiple simultaneous asynchronous requests in AJAX applications using the XmlHttpRequest object can be difficult, but this generalized XML response-handling code will help.

Thinking Asynchronously
Some developers approach this problem by assigning a different response-handling function to each request object created. That takes care of the differentiation problem, but now all the response processing code must have direct access to the request object and must include code that is specific to XMLHttpRequest and XMLHTTP object properties and methods. Each response-handling function would take the form of the processReqChanged function shown earlier, filtering ReadyStateChange events based on the readyState and status properties of the request object. If new objects or better techniques come along, you could end up needing to change a lot of code, instead of only the code that handles the communication. Instead, you should try to abstract the details of the communication from the response-handling code just as browsers and Web service frameworks abstract the details of HTTP connections from the process of sending the request.

That leaves the response content as the only remaining candidate for interpreting the nature of the response currently received. In this case you can be certain that if a response must be handled differently, then its content will be different. In this article, Drew McLellan suggests that this can be done by returning the name of the JavaScript function to call to handle the response within the XML response itself, and that a general processing function such as that shown at the beginning of this article can then use JavaScript's eval() function to call the specified function. But that method raises security concerns. For example, an attack might alter the HTTP response in transit (imagine the users of an online shopping site receiving an alert box with "Haha, we just stole your credit card!"). More importantly, though, it violates the fundamental design principles of abstraction and encapsulation. The server-side script should not need to know the names of client-side JavaScript functions. If this method were to become general practice, it would lead to horrific maintenance problems—the very maintenance problems such design principles are meant to avoid.

A slight modification of McLellan's suggestion offers some hope. If the returned "function name" is interpreted not as a function name but rather as a response type identifier, the client-side script could use a switch-case or if-then-elseif construct to dispatch the response XML to the correct handler. This is similar to assigning each request object its own handling function, except that all the AJAX-specific code would exist only in one place: the dispatching function. By dispatching only the XML response, it achieves the abstraction and encapsulation that we desire.

However, even this solution is too limited, as it restricts us to a one-to-one relationship between response and response handler. It could not elegantly handle a response of a complex type as shown below.

   <?xml version="1.0" encoding="UTF-8" 
               <user name="mw" since="200505122456" />
               <user name="dj" since="200505111253" />
               <message id="3" user="mw" val="Today?" />
               <message id="4" user="dj" val="Sure." />
With a complex response, the handling function would have to branch off many times or pass off chunks to other functions. For example, Listing 3 includes a typeid element with the value "chat". The distinct element value lets the client-side code dispatch the response to a special response handler for this particular response type. However, it would have to pass the entire response to this function, and the function would then need to branch further to handle the chatuserlist, chatmessages, and foo elements. More desirably the general handling function would pass off only the relevant parts of complex responses to appropriate handling code. In other words, you want your general response handling function to send the user list part of the response to the function that handles the user list; send the messages to the function that handles the chat messages, etc. Therefore, a general solution must be able to act appropriately on any element anywhere in the XML response. The best solution, then, is to register handling functions at the XML element level.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date