Put simply, Ajax allows us to request a resource without a page load. The response is made useful because we can manipulate it, drop the right data into the right kind of elements, and drop them into the page.

An excellent example of Ajax in action is Google Maps. As you zoom in and out of the map, you'll never see the whole screen flash and the entire page have to reload. The reason for this is that the new map images are being loaded with Ajax. You will, however, eventually see some grey rectangles that haven't yet been populated with map. This occurs because the Ajax request for the images or for the image locations is still going on and everything has not yet been fetched and placed into the page.

Another example of Ajax is how Twitter will "stream" tweets once you've loaded a page. This is accomplished by periodically making an Ajax request to the server for new tweet data. The resulting data is then looped through and wrapped in the proper HTML, which is then placed in the page and shown with a slick animation.

You may also see Ajax represented as "AJAX", since it stands for "Asynchronous JavaScript and XML". From this acronym definition it's quite clear that Ajax is not a language, but a combinations of different technologies for a common goal.

"Asynchronous" refers to the fact that Ajax is not in sync with traditional resource loading in the browser (i.e. the page load), "JavaScript" refers to... well, JavaScript, and "XML" is something will take a look at later on.

So, XML puts the "X" in "AJAX" and we're going to look at it later?

When all this emerged as a concept, XML was the favorite Content-Type as a response for Ajax. Since then, many people (including the developers of Rails) have come to prefer JSON over XML. The reason for this, as we'll soon see, is that JSON is great. ...I mean, because JSON is modeled after JavaScript objects and therefore plays nicely with JavaScript.

Familiarity with XML is definitely encouraged since you're bound to run across it somewhere, but it won't be here.

So how are these requests made exactly?

Let's get into that.

5.1 | XHR

In order to talk to the server asynchronously, we'll be using an XMLHttpRequest (XHR).

So, XML just came up again, huh?

I know, I know. Again, people started using XML for this purpose and all the X's and XML's in the concept names have hung around. But Rails now uses JSON by default, so that's what we'll be doing too.

From the name XMLHttpRequest, we can see that we'll be using HTTP, same as always, but in a new way: JavaScript will make the XMLHttpRequest and will also be responsible for handling the response.

There is a way to write out an XMLHttpRequest in plain JavaScript, but since we'll be making our Ajax requests with jQuery, let's move on to thinking about the Ajax response.

Chalk XMLHttpRequest up as another interesting thing to look into later.

5.2 | JSON

So when we make an Ajax request to our Rails app, the response body is going to be JSON which stands for JavaScript Object Notation. "JSON" is usually pronounced "jay-sahn", but some people insist on saying it like the given name "Jason".

The funny thing about JSON is that if you understand JavaScript objects, you basically already know JSON.

Hence the "J(ava)S(cript) O(bject)" of "JSON".

Take a look:

"{\"people\":[{\"name\":\"Brad Chase\",\"home_state\":\"Ohio\"}]}"

It's a little scrunched all on one line there and with all the quote escaping, but still familiar. In fact, the esacping above points to an important fact: JSON is the string representation of a given JavaScript object.

Hence the "N(otation)" in "JSON".

And that JSON above ends up being equivalent to the following JS object literal:

{
  people: [
    {
      name:       "Brad Chase",
      home_state: "Ohio"
    }
  ]
}

JSON also keeps with the tradition of our other languages thus far (HTML, CSS, and JavaScript) and is also sent as text. One difference with JSON though is that its Content-Type does not start with text/ like the others, but is instead application/json. Even so, it is still just plain text.

And even though the definition for "JSON" contains "JavaScript", JSON is not used exclusively by JS. For instance, Rails allows for reading from and writing to JSON with one of its core Ruby libraries.

5.3 | jQuery.ajax

So let's send an XHR with a jQuery.

First, assume that we have this markup somewhere in the current page:

<div id="people"></div>

and we want to populate it with people's names and their home state names.

Let's say that I'm the only person stored in the database on the server, and so the JSON response we'll be receiving will be the following:

"{\"people\":[{\"name\":\"Brad Chase\",\"home_state\":\"Ohio\"}]}"

Now all we need is the JavaScript:

// using jQuery to send an Ajax request for the resource '/people.json'
$.ajax('/people.json', {
  // the callback for the response
  complete: function(jqXHR, textStatus) {
    // parse the response body into a JS object
    var data = $.parseJSON(jqXHR.responseText);

    // find the parent div to add to
    var div = $('#people');

    // loop through the people for the json response
    $.each(data.people, function(i, person){
      // build a <p> to contain the person's information
      var p = $('<p>', {text: person.name + " is from " + person.home_state});

      // add the <p> to the container <div>
      div.append(p);
    });
  }
});

Play with the jsFiddle.

This leaves us with the following markup (whitespace added):

<div id="people">
  <p>Brad Chase is from Ohio</p>
</div>

There's quite a bit of JavaScript above, but the comments should explain every step of the way. Take a minute to see what all is going on, then meet me back here.

So you'll see that we're calling the .ajax method on the $ variable at the very beginning, passing two arguments: a path string and a settings object. At the moment, we only have one one item in the settings object: a complete callback function to process the response.

Two notes here.

First, we can skip the first argument altogether and pass the URL along in the settings object under the url property like this:

 
$.ajax({ 
  url: '/people.json',
  complete: function(jqXHR, textStatus) { ... }
});

Second, the callback doesn't ride along on the HTTP request or anything, but since jQuery is also handling the response through .ajax() (in addition to making the request), this is a good place to register callbacks.

More on callbacks shortly, but right now we just need to know that they are processing the (JSON) response.

One thing you may have noticed is that we are not specifying an HTTP verb for the request. By default, .ajax will make a GET request, but this can be changed with the settings object using the type property. If, for instance, we wanted to perform a POST instead we could include the pair type: "POST" in the settings object.

There's definitely more to look at here, but let's toss some things in variables so we can better see the jQuery calls we're making.

Let's start by putting our URL and callback method in their own variables:

var url = '/people.json';

var completionCallback = function(jqXHR, textStatus) {
  var data = $.parseJSON(jqXHR.responseText);
  var div = $('#people');
  $.each(data.people, function(i, person){
    var p = $('<p>', {text: person.name + " is from " + person.home_state});
    div.append(p);
  });
};

$.ajax(url, {complete: completionCallback});

Play with the jsFiddle.

If you find yourself writing the same callback twice for some reason, this is a good solution. Otherwise, doing everything inline with an anonymous function is fine.

This works the same as before, score.

But there is something we didn't really bother to consider earlier: What happens if we can't reach the server?

In the case of a normal HTTP request, if the server is unreachable, you'll end up seeing some kind of message to that effect. In this case, it's our responsibility to handle this problem.

Luckily, regardless of how the request goes, the callback designated by complete will be run. This is where textStatus becomes helpful, because it will let us differentiate success from error. In fact, it does this quite literally with "success" and "error".

Let's refactor completionCallback to reflect this:

completionCallback = function(jqXHR, textStatus) {
  if(textStatus == "success"){
    var json = $.parseJSON(jqXHR.responseText);
    var div = $('#people');
    $.each(json.people, function(i, person){
      var p = $('<p>', {text: person.name + " is from " + person.home_state});
      div.append(p);
    });
  } else {
    alert("We're sorry, something went wrong...");
  }
};

Play with the jsFiddle.

The callback above will work just fine, but there are a couple other ways to do this that are more declarative and readable. They both involve individual callbacks for success and error though, so let's define those now:

var successCallback = function(data, textStatus, jqXHR) {
  var div = $('#people');
  $.each(json.people, function(i, person){
    var p = $('<p>', {text: person.name + " is from " + person.home_state});
    div.append(p);
  });
};

var errorCallback = function(jqXHR, textStatus, errorThrown) {
  alert("We're sorry, something went wrong...");
};

One of the important thing to notice here is that the parameters change for these callbacks. Also, keep in mind that we are only naming the parameters here, the order that arguments are passed into these callbacks is dictated by the inner workings of jQuery.

In particular, notice the first parameter for the successCallback is data. This will hold the JS object equivalent of the JSON response, so we won't bother parsing it out ourselves.

So now that we have these callbacks defined, let's use them.

$.ajax(url, {
  success: successCallback,
  error:   errorCallback
});

Play with the jsFiddle.

Here we can see that we just end up stuffing these callbacks under the right properties in the settings object to register them.

Now, there is an equivalent version to what we just did above, but it uses a different syntax that might not make sense at first. To understand why it works, we'll need to take a deeper look at $.ajax and see what exactly is happening here.

First of all, why are are callbacks even necessary here?

Callbacks are necessary because the response is not immediately available. Remember that obtaining the JSON we want to manipulate requires an asynchronous HTTP round trip that is going to take some amount of time. Instead of waiting around and doing nothing, execution continues on after the request is made.

Tetonic plates shift as time marches... actually, just a few milliseconds elapse.

Then once the response is received and there is a break in execution, the callback is run.

Because of this fact, it's handy to have the jqXHR (a jQuery flavored XHR) around to adjust as needed. Better yet, $.ajax returns the jqXHR that it creates.

If you were playing around with this and did a console.log of the jqXHR that is passed into any of the callbacks, you'd see that it is an object that has not only the responseText (JSON) and status (the HTTP status code), but it has functions like complete, success, and error.

Play with the jsFiddle.

We can pass these methods our callbacks and they too will return the jqXHR. This is important because it means that we can chain our callback definitions, because each callback registration methods returns the jqXHR itself, the one we want to continue adding on to.

Here's what that looks like:

$.ajax(url)
  .success(successCallback)
  .error(errorCallback);

Play with the jsFiddle.

This is equivalent to the last two $.ajax calls we've written.

Also, notice here that Javascript doesn't care if we split a single line of code onto multiple lines of text, it just keeps looking until it finds a ;, which it recognizes as the end of a line.

Putting everything above on one line would look like this:

$.ajax(url).success(successCallback).error(errorCallback);

We can even pass some data along to the server, using the data property in the settings object, like so:

var data = {foo:'bar'};

$.ajax(url, { data: data })
  .success(successCallback)
  .error(errorCallback);

This will automatically URL encode the property/value pairs in data and pass them on to the server as query string parameters for a GET request.

If we instead set type: "POST" to do a POST instead, the contents of data will instead be sent as POST data.

In fact, we could instead use .post() instead of .ajax() in this case and skip the type: "POST".

A note on jQuery callback names

Deprecation Notice: The jqXHR.success(), jqXHR.error(), and jqXHR.complete() callbacks will be deprecated in jQuery 1.8. To prepare your code for their eventual removal, use jqXHR.done(), jqXHR.fail(), and jqXHR.always() instead. - jQuery's website.

So why are these deprecated callbacks used above?

Because the current version of Rails (3.2.8) uses jQuery 1.7 and it works just fine using the older versions of the callback names.

5.4 | XML

So now that we've seen the way things work with JSON, let's take a quick look at how we'd use XML instead.

Yeah, I felt obligated to toss this in.

First, XML stands for Extensible Markup Language, which means that XML, like HTML, is a markup language but it is extensible, which means that we can create our own tags.

So let's look at what our $.ajax() example above would look like if we were getting an XML response instead.

Here's some XML that would represent the same information as the JSON above:

<people>
  <person>
    <name>Brad Chase</name>
    <homestate>Ohio</homestate>
  </person>
</people>

And here's the JavaScript to request and process it:

// using jQuery to send an Ajax request for the resource '/people.xml'
$.ajax('/people.xml')
  .success(function(xml) {
    // we can pass the XML text into $() and 
    // walk it just as we would with the DOM
    var people = $(xml).find('people person');

    // find the parent div to add to
    var div = $('#people');

    // loop through the people for the json response
    $.each(people, function(i, person){
      var name       = $(person).find('name').text();
      var home_state = $(person).find('homestate').text();

      // concatenante <p> text together
      var text = name + " is from " + home_state;

      // build a <p> to contain the person's information
      var p = $('<p>', {text: text});

      // add the <p> to the container <div>
      div.append(p);
    });
  });

Play with the jsFiddle.

Conclusion

So there you have it, Ajax. As you surf around the Web, keep an out of asynchronous resource loading; it's everywhere.

Later on, we'll be using Rails' special version of Ajax when we build our application, but these jQuery methods are what sit under its hood and are good to understand.

And with that, you are up to speed on general web concepts! Way to go!