Tuesday, April 22, 2008

Universally Related Popup Menus AJAX Edition: Part 3

The XmlHttpObjectManager Object

The XmlHttpObjectManager is a private member variable of the callServer() function (line 141). It's a static class, so we never create an instance of it. Rather, it just houses some variables and methods that relate to the XmlHttpRequest object. Its main purpose is to act as a wrapper to the XmlHttpRequest object because we only create one that we reuse every time we want to call the server. The real object is stored in the private XmlHttpObject variable (line 143). To get a reference to it, we call getXmlHttpInstance(), which is one of two public functions exposed via the interface object (line 144). The interface object uses JavaScript Object Notation (JSON) which is a standardized way of denoting an object literal, much the same way that XML is used to describe data. Hence, its syntax is quite a bit different from regular JavaScript The entire object is located between two curly braces {}. Each public property is notated by its name, followed by a colon (:) and the value. The properties are then separated by commas.

Now let's take a look at our interface's methods and properties.

The getXmlHttpInstance() method (line 146) is what I like to call a "mutating function". Here's why. The first time it's called, it returns a new XmlHttpObject (line 150) but it also sets itself to a new function that returns the private xmlHttpObject variable (line 148). Oddly, this has no effect on the execution of the function because it's already on the stack, so the changes don't take effect until after the current one finishes executing. Every successive call afterwards receives the same xmlHttpObject variable.

The state_change() method is the second one that is accessible via the XmlHttpObjectManager's public interface (line 153). Its job is to check the xmlhttp.readyState property every time the xmlhttp.onreadystate property changes. We have to check the readyState property to make sure the object has finished bringing back all the data from the server (line 155). There are a total of five possible states but we're testing against a value of 4. Here's the list of ready state values and their meaning:

  1. The request is uninitialized (before you've called open()).
  2. The request is set up, but not sent (before you've called send()).
  3. The request was sent and is in process (you can usually get content headers from the response at this point).
  4. The request is in process; often some partial data is available from the response, but the server isn't finished with its response.
  5. The response is complete; you can get the server's response and use it.

Once we hit the last loading state, we can run the call back function (line 159). Any errors that occur in the callback function will be trapped by the try/catch block so that a message can be displayed (line 163). The list is again passed along in the this pointer.

The following properties are also accessible via the interface object: RUN (line 171), READY_STATE (line 173), and STATUS (line 175). They are JSON objects containing named constants. Here's the first part of the XmlHttpObjectManager object, including its private interface variable (we'll see how it's made public in a moment)

141var XmlHttpObjectManager = (function()
142{
143 var xmlHttpObject = null;
144 var interface =
145 {
146 getXmlHttpInstance:function()
147 {
148 interface.getXmlHttpInstance = function() { return xmlHttpObject; };
149
150 return new XmlHttpObject();
151 }
152 ,
153 state_change:function(xmlhttp, callBackFunction, READY_STATE, STATUS)
154 {
155 if (xmlhttp.readyState == READY_STATE._DONE_LOADING)
156 {
157 try
158 {
159 callBackFunction.call(this, xmlhttp, STATUS);
160 }
161 catch (e)
162 {
163 alert( "An error occurred in the AJAX call back method:"
164 + "\nNumber:\t" + e.number
165 + "\nName:\t" + e.name
166 + "\nMessage:\t" + e.message );
167 }
168 }
169 } //public constants
170 ,
171 RUN: { _ASYNCHRONOUSLY:true }
172 ,
173 READY_STATE: { _DONE_LOADING:4 }
174 ,
175 STATUS: { _OK:200 }
176 };

No comments: