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
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
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
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
, 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