Last year I began a series called “Ajax From the Ground Up”, that consisted of two articles describing how to implement Ajax from scratch using pure JavaScript. Because I was busy with other things, and due to minimal interest shown in the articles, I never wrote the third part to the series.
But I didn’t feel comfortable leaving it permanently unfinished, so with this article, I’ll complete the 3-part series that will teach you how to fully implement Ajax calls in your pages using raw JavaScript.
If you haven’t seen the previous articles, you can do so using the links below:
Ajax From the Ground Up: Part 1 — XMLHttpRequest
Ajax From the Ground Up: Part 2 — Sending Data to the Server
The Code Written So Far
When I left off the series, the code we created consisted of two functions. The first function we built creates the XMLHttpRequest
(XHR) object that’s used for the Ajax calls, ensuring that the object is able to be created before going any further, and doing so in a cross-browser fashion. The next function we created checks to see if the XHR object exists, and if it does, it then sends the request to the server, and makes a call to a specific file.
Here is the code from the two previous tutorials, with the functions reversed (since the XHR function is more of a utility function):
// This function checks to see if the XHR object exists // and proceeds accordingly function ajaxTest() { var ajaxCapable = getXhrObject(); if (ajaxCapable) { ajaxCapable.onreadystatechange = function() { checkServerResponse(ajaxCapable); }; ajaxCapable.open("POST", "file-requested.txt", true); ajaxCapable.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); ajaxCapable.send(null); document.getElementById("output1").innerHTML = "Your Browser Supports Ajax!"; } else { document.getElementById("output1").innerHTML = "Your Browser Does Not Support Ajax!"; } } // This function will be built in the current tutorial function checkServerResponse() { // do something } // This function creates the XHR object function getXhrObject() { var xhrObject = false; // Most browsers (including IE7) use the 3 lines below if (window.XMLHttpRequest) { xhrObject = new XMLHttpRequest(); } // Internet Explorer 5/6 will use one of the following else if (window.ActiveXObject) { try { xhrObject = new ActiveXObject("Msxml2.XMLHTTP"); } catch(err) { try { xhrObject = new ActiveXObject("Microsoft.XMLHTTP"); } catch(err) { xhrObject = false; } } } return xhrObject; }
You’ll notice the code above also includes a third function (lines 17-20) called checkServerResponse
. This is the function that we’ll be building in this tutorial. Also, I’ve made a small change to the line in the first function that calls the checkServerResponse
function (lines 5-6). Instead of calling the function immediately (which would happen because of the passed parameter), I’ve placed it inside of an anonymous function, to ensure it doesn’t initiate until the correct event is fired.
Checking the XHR Object’s readyState
Property
Before we start building this new function, keep in mind at what point in our code this function is called. This function will run every time the onreadystatechange
event handler is triggered. Remember that the onreadystatechange
event is fired every time the server responds. With this in mind, here is the start of our new function:
function checkServerResponse(ajaxCapable) { if (ajaxCapable.readyState === 4) { } }
The XHR object (which, if you recall, is stored in the ajaxCapable
variable, which is passed into the function), has a property called readyState
that changes depending on the status of the server’s response. The only value we’re really concerned with is the value 4
, which indicates that the request from the server has completed. All the possible values for this property are as follows:
- 0 = Uninitialized
- 1 = Loading
- 2 = Loaded
- 3 = Interactive
- 4 = Complete
Theoretically, it’s possible to check for all these values, and do something different at each level, but because these changes happen so rapidly it’s pointless to even attempt to use these values. So, the only value we’ll be checking for is the value of “4”. Checking to see if the value is “4” will ensure that nothing happens unless the response is complete, even though technically the checkServerResponse
function will be initializing multiple times before the “complete” stage is reached.
Checking the XHR Object’s status
Property
The next check in our function will access the status
property of the XHR object. The status
property tells us by means of a numeric value what type of response was received by the server. If you’ve ever seen a “404 error” message on a web page, then you’ve already seen the “status” of a server’s response. So, with the next line of code, we’re going to ensure that the server’s response is what we expect. Just because the server responded, doesn’t necessarily mean we’ve received any data. If the file we requested was not found, then the server would not receive anything, even though the “complete” message has been sent.
The two status levels we will be looking for are 200
(which means “ok”) and 304
(which means “not modified”, thus allowing access to a cached version). Here’s our updated function:
function checkServerResponse(ajaxCapable) { if (ajaxCapable.readyState === 4) { if (ajaxCapable.status === 200 || ajaxCapable.status === 304) { // do something } } }
Now the function will only “do something” if the “complete” message is received (“4”), and if either the numeric value “200” or the numeric value “400” is received as the status of the current server request.
The XHR Object’s responseText
Property
Finally, once we have received the “ok” by means of the two if
statements, then it’s safe to obtain the data that the server has sent. This is done by accessing the responseText
property of the XHR object. The value of that property could be an HTML document, an XML file, or some other data, depending on what type of request we made and what kind of file we requested.
Here’s the function with the new line of code added:
function checkServerResponse(ajaxCapable) { if (ajaxCapable.readyState == 4) { if (ajaxCapable.status == 200 || ajaxCapable.status == 304) { document.getElementById("content").innerHTML = ajaxCapable.responseText; } } }
In the final line added above (line 4), we’ve written the contents of the responseText
property to the element in the page that has an id
of “content”. Theoretically, you could do what ever you want with the data that’s returned, so this is just an example to show you what’s possible.
What if the Data Returned is XML?
If the server’s response returns data in the form of XML, then the data will be accessed through a different property called responseXML
. In this case, we obviously would not just write the contents of the server response, but instead we would parse the contents, and then display them accordingly. The code might look as follows:
function checkServerResponse(ajaxCapable) { if (ajaxCapable.readyState == 4) { if (ajaxCapable.status == 200 || ajaxCapable.status == 304) { var myData = ajaxCapable.responseXML; // Do something with the myData object here... } } }
So, instead of writing the XML to the HTML page (which would create invalid markup), we instead place the contents of the data into a variable, from which we can then extract the data however we like. Using Firebug would be useful in such an instance, since we could display the contents of the XML in the Firebug console and examine it accordingly.
Conclusion
That’s all the code you need to successfully make cross-browser Ajax requests with raw JavaScript. Keep in mind that using a JavaScript library would make this process much simpler, so I highly recommend you learn to implement Ajax through jQuery or another library. However, if you want to avoid the code overhead in using an entire library for Ajax calls, then these functions could provide a workable alternative.
Even if you decide to use a library, I still think it’s important that developers understand the different parts of an Ajax call so they can be familiar with exactly what is taking place behind the scenes. Having this understanding will unquestionably help you to create more intuitive and usable Ajax-driven pages.
You can download or view a demo of the complete code using the buttons below.
Thanks for finishing the 3rd. =)
I’ve been looking for a good walk-through and this did the trick. Thanks!
it is good article and i like it
its that trick, which i was finding since a long time. thanks.
thanks so much for sharing this. hope many people will find it useful as i did. just one question: is the onreadystatechange event really fired every time the server responds?
ve been looking for a good walk-through and this did the trick.
Thanks. Very clean & direct to the point.
Exellent tutorial
Really interesting, just read the 3 tutorials all at once and understood all at once.
Do you have anywhere a tutorial showing how to exploit ajaxCapable.responseXML ?
This tutorial deserves a thumbs up.
Lucid, well structured and informative.
Thanks! Excellent to understand how it works behind the scene.
very well explained! thanks for finishing this tutorial it definitely helped me :) ::cheers::
In other ajax libraries there is a fail call back in addition to the success: callback, how would a fail callback be handled here.
You would just have to add an ‘else’ statement to go along with the if statement that indicates success.
could you show a short example of this, thanks
I think that should be enough. Just put your fail code where it says
// fail
.