The Ajax wrapper that we will be creating is simply called Ajax, and is an object that follows the Singleton pattern, which we will cover in detail in Chapter 14, "Singleton Pattern." This object will handle all requests to the server through the XHR as a single object that will always be reliable and never change stateshence the Singleton pattern. This way, any object that needs to make a request will do so through the same object, keeping the requests structured and organized. In order to create this object, we first need to simply construct it as in Listing 6.1.
Listing 6.1. Constructing the Ajax Object (Ajax.js)
After the object is constructed, we can create all the methods we will need to call in order to make requests, check the ready state, and receive a response object for parsing and either displaying or manipulating the data on the client side. We will start by covering how to create a method to handle making our XHR requests.
One of the most important functionalities of our Ajax object is making XHRs. In order to make this process more streamlined and easier to manage, we will be creating a method named makeRequest. This method will take three parameters: The first is a method in which to make the request, which will consist of either a POST or a GET method. The second parameter is the URL in which to make the request; this URL also will include our query string for passing data to the server when we make a request. The last parameter is the callback method, which we will want to invoke to handle the response when the ready state is completed. Listing 6.2 shows the entire method for handling this functionality.
Listing 6.2. Streamlining the Process of Making XHRs (Ajax.js)
This method should look very familiar because it contains all the same functionality that we used to create an XHR object and send that data to the server in Chapter 2. The difference with this method is that it wraps all this functionality into an easy-to-manage object that we can access from anywhere in a large application. We start by deciphering which XHR object to instantiate based on the browser type. After we instantiate the appropriate XHR object, we set the onreadystatechange event to the callback method that was provided as the third parameter of this method. This means that the callback method you provide to this method will be fired when the XHR has been received, and is ready to be parsed for displaying or manipulating data on the client side of the application. The last two methods are the open and send methods of the XHR object. The open method initializes the request, and specifies the method in which to make the request, the URL to make the request to, plus a query string, if one applies, and a Boolean for asynchronous versus synchronous. We set the Boolean to true by default because we do not want to make synchronous requests; they will freeze your application until the response has been received from the request. If you are making numerous requests in a large application, this will render your application unusable. The last method, the send method, will be used to actually send the HTTP request to the server and wait to receive the response. This method takes the same URL as the open method, plus any key/value pairs that may exist in a query string.
After this method instantiates the XHR object and makes the request based on the information that we provide it, a response will be received in the callback method that we set. The callback method will need to check what is called the ready state of the XHR object and either parse the object after the ready state is completed or handle any HTTP status code errors that may be returned from the server. In order to check the ready state of the XHR object, we will be creating a method that does this for us called checkReadyState, which will become part of the Ajax object.
The Ready State
Listing 6.3. Checking the Ready State of the XHR (Ajax.js)
This method is very similar to the method that we created in Chapter 2, but it is now encapsulated into the Ajax object to lend structure and organization to our code base. For each state of the readyState, we set a custom loading message to the innerHTML property of the HTML element that we passed the ID for as a parameter. This message can become anything you would like to change it to. Each state can actually have its own loading message passed as a parameter to the method to give the requesting object more power over what messages display. For instance, say that we have a request to update an inbox of an email application. We could show states specific to this request, such as Retrieving new mail, for example. Remember that after this object has been created, it can be manipulated to handle any custom functionality you need to handlethis is the beauty of creating an object-oriented code base for our applications.
After the readyState has reached a state of 4, the XHR object is complete and ready for use. At this point, one of two things can happen: The HTTP status can be successful, or it can return an informational, redirection, client, or server error code. Based on the code that is returned, we will decide how to handle the client side. We will cover this in much more depth in Chapter 9, "Extending the Engine," when we create a custom object to extend the Ajax object and handle all the HTTP status codes available. One thing I am sure you noticed is that we are setting an AjaxUpdater object's isUpdating property to false. I'm sure you are wondering what this object is and why we are setting this property. This object will be created in the next section of this chapter and will be used to handle all Ajax requests. It will be used as one degree of separation between the client-side objects and the engine, and will keep our code base much more organized and secure. But before we cover this object, we will see how to get the response object after the readyState is completed.
This last method, called geTResponse, is extremely simple because it only deciphers what type of response property needs to be returned to the requesting object. Take a look at Listing 6.4 to see how we are handling this functionality.
Listing 6.4. Getting the Appropriate Response Object (Ajax.js)
In order to get the response from the Ajax object, we simply call this method from our callback method after the readyState is complete, and it will return the appropriate response property. It returns the appropriate response property based on the response header that is returned with the response from the server. If the Content-Type response header has an index of the string xml in it, we know that the response is in the form of XML and should therefore be returned to the callback method as a DOM-compatible document object of the response from the server. Otherwise, this method returns the responseText property, which is a string version of the response from the server.
Now that we have a custom object to control and manage all of our Ajax requests, we can add one more layer of abstraction to the code to make our requests more manageable and secure.