CodeinWP CodeinWP

Ajax From the Ground Up: Part 3 — Getting a Response From the Server

Ajax From the Ground Up: Part 3Last 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.

16 Responses

  1. Me says:

    Thanks for finishing the 3rd. =)

  2. Super Awesome Guy says:

    I’ve been looking for a good walk-through and this did the trick. Thanks!

  3. sana says:

    it is good article and i like it

  4. ASAD ULLAH says:

    its that trick, which i was finding since a long time. thanks.

  5. Tbasket says:

    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?

  6. allan says:

    ve been looking for a good walk-through and this did the trick.

  7. TruckMan says:

    Thanks. Very clean & direct to the point.

  8. Robert says:

    Exellent tutorial

  9. Loup says:

    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 ?

  10. BandofMilliband says:

    This tutorial deserves a thumbs up.

    Lucid, well structured and informative.

  11. Alexandre Bourlier says:

    Thanks! Excellent to understand how it works behind the scene.

  12. himanshu says:

    very well explained! thanks for finishing this tutorial it definitely helped me :) ::cheers::

  13. Neil Caffery says:

    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.

      • neil caffery says:

        could you show a short example of this, thanks

        • function checkServerResponse(ajaxCapable) {
            if (ajaxCapable.readyState == 4) {
              if (ajaxCapable.status == 200 || ajaxCapable.status == 304) {
                document.getElementById("content").innerHTML = ajaxCapable.responseText;
              } else {
                // fail
              }
            }
          }
          

          I think that should be enough. Just put your fail code where it says // fail.

Leave a Reply

Comment Rules: Please use a real name or alias. Keywords are not allowed in the "name" field and deep URLs are not allowed in the "Website" field. If you use keywords or deep URLs, your comment or URL will be removed. No foul language, please. Thank you for cooperating.

Markdown in use! Use `backticks` for inline code snippets and triple backticks at start and end for code blocks. You can also indent a code block four spaces. And no need to escape HTML, just type it correctly but make sure it's inside code delimeters (backticks or triple backticks).