Doing it Asynchronously

Regardless of what you’ve heard about Web 2.0, why it’s cool, why it’s not really 2.0, or why the term Web 2.0 may actually be important, one thing is certain. It’s very shagadellic and it’s all about asyncronicity baby!

Yes that’s right, everyone is doing it asynchronous now, newbies and hackers alike. And why not? It’s all the rage! I mean, how boring was the way your grandparents did it? So mundane, always following the same routine:

  1. Load
  2. Wait for a response
  3. Click
  4. Repeat

Are you really happy with the result of a simple load, wait, click, repeat? Maybe you enjoy the repetitiveness since you’re web site ‘seems’ to enjoy it equally, but what if there’s more?. To enjoy the best experience of asyncronicity, all you need are the Ajax twins: XmlHttpRequest and ActiveXObject(“Microsoft.XMLHTTP”) — but that’s where it begins to get a little complicated. It seems these two have been taking over the minds of many a young web developer, corrupting their thoughts with wild imaginative fantasies. Now, day-in and day-out, 24/7, all the web developers can think about is:

  1. Load
  2. Wait for a response
  3. Click
  4. Click
  5. Click
  6. Click
  7. Click
  8. Click
  9. Click

Going with the flow

All these asynchronous communications change the very nature of your application’s flow. You can’t rely on that mundane load, wait, click, repeat cycle because the page never fully loads again, only little pieces of it do. For instance, take this common simple administration tool for a news item list on a website:

Common News Tool

The ‘check mark’ and ‘x’ symbols represent the ‘active’ state of the items in the list.

To ‘activate’ an item, the user would simply click the check box or the x and several things may happen. If you’re using the traditional workflow, your web application will probably do something like this where the page is forced to reload:

Traditional Application Flow

This is a typical “Web 1.0” application flow. You click, a request is sent to the server, it responds, and the entire page is reloaded to reveal the new change. Often, you’re left sitting at the top of the page and forced to scroll down to even see the change. What fun.

Alternatively, if you’re going asynchronous with Ajax, you’ll end up with something that looks a little more like this, where only small protions of the page change using the appropriate DOM scripting:

Ajax Application Flow

No reloading except for the manipulation of the page with your favorite DOM methods. So where’s the problem? We’ll it’s not really a problem — if you know what you’re doing. The thing you have to remember is that you’re doing things asynchronously now. Requests are going out every time you click the buttons, but they don’t necessarily come back in the same order. Huh? Let me explain with an example. Click this button several times quickly in succession:

<form action="" onsubmit="return false;" style="display:block; border:1px solid #ccc; padding:1em;">
<script src="http://jeffreysambells.com/openprojects/PHP/sleeperajax.js"></script>
<input type="button" value="Make a request" onclick="doRequest($('ajaxRequestList'));">
<h4>Requests</h4>
<ol id="ajaxRequestList" style="background-color:#eee; height:8em; overflow:scroll;"></ol>
</form>

Notice the order of the requests coming back? The request number represent the order you clicked the button but the order of the list represents the order they were completed by the server. When you click the button, a request is sent to the server and in this case all I’m doing is simulating some server traffic by sleeping the PHP script for a random time:

<?
header("Cache-Control: no-cache, must-revalidate");
sleep( $time = (2/rand(1,8)) );
echo "$time";
die();
?>

and then sending back the $time before completing the request. If you wait at least 2 seconds between each button click, it’ll probably return requests in the same order because the initial request will complete before the following request. But, if you click it quickly several times quickly in succession, in this case less than 2 seconds apart, you may have a request of 1.5 seconds followed by a request of 0.5 seconds. When that occurs, the second request will finish and complete before the earlier request! This demonstrates asynronous in action - it’s out of sync and out of order, running at the same time as other requests.

Handling Asynchronous Requests

If you check out the JavaScript I’m using to do the request it looks something like this:

var counter=0;
function doRequest(e){
	var num = ++counter;
	new Ajax.Request("http://jeffreysambells.com/openprojects/PHP/sleeper.php",
	{
		onComplete:function(t){
			e.innerHTML += "<li>Request <strong>" + num + "</strong> <em>(took " + t.responseText + " seconds)</em></li>";
		}
	});
}

All it does is make an Ajax request (using the Prototype library Ajax object, since it’s already loaded in my blog) and then processes the result when complete. The key thing to remember is that the action you want to take as a result of the request must be placed on the onComplete handler of the Ajax object (or onSuccess in the case of prototype if you’re doing error handling). I often see Ajax rookies doing something similar to:

var counter=0;
function doRequest(e){
	var num = ++counter;
	new Ajax.Request("http://jeffreysambells.com/openprojects/PHP/sleeper.php");
	e.innerHTML += "<li>Request <strong>" + num + "</strong> <em>(took " + t.responseText + " seconds)</em></li>";
}

which is just plain wrong. As I demonstrated earlier, The XmlHttpRequest object is asynchronous, this means that the

new Ajax.Request("http://jeffreysambells.com/openprojects/PHP/sleeper.php");

line will execute, but may not return before the

e.innerHTML += "<li>Request <strong>" + num + "</strong> <em>(took " + t.responseText + " seconds)</em></li>";

line executes. If you want your script to wait until the request is complete, you must handle the remaining script from within the onComplete handler by splitting your JavaScript code into objects and methods, then calling the appropriate one when each request is complete.

{.caution}In the ‘wrong’ way above, there’s the additional problem of using t.responseText, which isn’t in the scope of the doRequest() function, but we’ll discuss that mistake another time.

It’s that simple. Nothing too complicated just a complete shift in the ‘top down execution’ approach you’re probably more familiar with. All you have to do is remember that the A in Ajax means Asynchronous. That’s the key.

If you’d like to learn more about Ajax, I’d suggest first reading the original Ajax article by Jesse James Garrett at Adaptive Path “Ajax: A New Approach to Web Applications” and the many excellent resources over on ajaxian.com but in the mean time have fun with Ajax — the more you do it the better you’ll get.