14 min read

Ajax is not a piece of software in the way we think about JavaScript or CSS being a piece of software. It’s actually a lot more like an overlaid function. But what does that mean, exactly?

Why Ajax is a bit like human speech

Human speech is an overlaid function. What is meant by this is reflected in the answer to a question: “What part of the human body has the basic job of speech?” The tongue, for one answer, is used in speech, but it also tastes food and helps us swallow. The lungs and diaphragm, for another answer, perform the essential task of breathing. The brain cannot be overlooked, but it also does a great many other jobs. All of these parts of the body do something more essential than speech and, for that matter, all of these can be found among animals that cannot talk. Speech is something that is overlaid over organs that are there in the first place because of something other than speech.

Something similar to this is true for Ajax, which is not a technology in itself, but something overlaid on top of other technologies. Ajax, some people say, stands for Asynchronous JavaScript and XML, but that was a retroactive expansion. JavaScript was introduced almost a decade before people began seriously talking about Ajax. Not only is it technically possible to use Ajax without JavaScript (one can substitute VBScript at the expense of browser compatibility), but there are quite a few substantial reasons to use JavaScript Object Notation (JSON) in lieu of heavy-on-the-wire eXtensible Markup Language (XML). Performing the overlaid function of Ajax with JSON replacing XML is just as eligible to be considered full-fledged Ajax as a solution incorporating XML.

Ajax helps the client talk to the server

Ajax is a way of using client-side technologies to talk with a server and perform partial page updates. Updates may be to all or part of the page, or simply to data handled behind the scenes. It is an alternative to the older paradigm of having a whole page replaced by a new page loaded when someone clicks on a link or submits a form. Partial page updates, in Ajax, are associated with Web 2.0, while whole page updates are associated with Web 1.0; it is important to note that “Web 2.0” and “Ajax” are not interchangeable. Web 2.0 includes more decentralized control and contributions besides Ajax, and for some objectives it may make perfect sense to develop an e-commerce site that uses Ajax but does not open the door to the same kind of community contributions as Web 2.0.

Some of the key features common in Web 2.0 include:

Partial page updates with JavaScript communicating with a server and rendering to a page

An emphasis on user-centered design

Enabling community participation to update the website

Enabling information sharing as core to what this communication allows

The concept of “partial page updates” may not sound very big, but part of its significance may be seen in an unintended effect. The original expectation of partial page updates was that it would enable web applications that were more responsive. The expectation was that if submitting a form would only change a small area of a page, using Ajax to just load the change would be faster than reloading the entire page for every minor change. That much was true, but once programmers began exploring, what they used Ajax for was not simply minor page updates, but making client-side applications that took on challenges more like those one would expect a desktop program to do, and the more interesting Ajax applications usually became slower. Again, this was not because you could not fetch part of the page and update it faster, but because programmers were trying to do things on the client side that simply were not possible under the older way of doing things, and were pushing the envelope on the concept of a web application and what web applications can do.

Which technologies does Ajax overlay?

Now let us look at some of the technologies where Ajax may be said to be overlaid.

JavaScript

JavaScript deserves pride of place, and while it is possible to use VBScript for Internet Explorer as much more than a proof of concept, for now if you are doing Ajax, it will almost certainly be Ajax running JavaScript as its engine. Your application will have JavaScript working with XMLHttpRequest, JavaScript working with HTML, XHTML, or HTML5; JavaScript working with the DOM, JavaScript working with CSS, JavaScript working with XML or JSON, and perhaps JavaScript working with other things.

While addressing a group of Django developers or Pythonistas, it would seem appropriate to open with, “I share your enthusiasm.” On the other hand, while addressing a group of JavaScript programmers, in a few ways it is more appropriate to say, “I feel your pain.” JavaScript is a language that has been discovered as a gem, but its warts were enough for it to be largely unappreciated for a long time. “Ajax is the gateway drug to JavaScript,” as it has been said—however, JavaScript needs a gateway drug before people get hooked on it. JavaScript is an excellent language and a terrible language rolled into one.

Before discussing some of the strengths of JavaScript—and the language does have some truly deep strengths—I would like to say “I feel your pain” and discuss two quite distinct types of pain in the JavaScript language.

The first source of pain is some of the language decisions in JavaScript:

The Wikipedia article says it was designed to resemble Java but be easier for non-programmers, a decision reminiscent of SQL and COBOL.

The Java programmer who finds the C-family idiom of for(i = 0; i available will be astonished to find that the functions are clobbering each other’s assignments to i until they are explicitly declared local to the function by declaring the variables with var. There is more pain where that came from.

The following two functions will not perform the naively expected mathematical calculation correctly; the assignments to i and the result will clobber each other:

function outer()

{

result = 0;

for(i = 0; i {

result += inner(i);

}

return result

}

function inner(limit)

{

result = 0;

for(i = 0; i {

result += i;

}

return result;

}

The second source of pain is quite different. It is a pain of inconsistent implementation: the pain of, “Write once, debug everywhere.” Strictly speaking, this is not JavaScript’s fault; browsers are inconsistent. And it need not be a pain in the server-side use of JavaScript or other non-browser uses. However, it comes along for the ride for people who wish to use JavaScript to do Ajax. Cross-browser testing is a foundational practice in web development of any stripe; a good web page with semantic markup and good CSS styling that is developed on Firefox will usually look sane on Internet Explorer (or vice versa), even if not quite pixel-perfect. But program directly for the JavaScript implementation on one version of a browser, and you stand rather sharp odds of your application not working at all on another browser. The most important object by far for Ajax is the XMLHttpRequest and not only is it not the case that you may have to do different things to get an XMLHttpRequest in different browsers or sometimes different (common) versions of the same browser, and, even when you have code that will get an XMLHttpRequest object, the objects you have can be incompatible so that code that works on one will show strange bugs for another. Just because you have done the work of getting an XMLHttpRequest object in all of the major browsers, it doesn’t mean you’re home free.

Before discussing some of the strengths of the JavaScript language itself, it would be worth pointing out that a good library significantly reduces the second source of pain. Almost any sane library will provide a single, consistent way to get XMLHttpRequest functionality, and consistent behavior for the access it provides. In other words, one of the services provided by a good JavaScript library is a much more uniform behavior, so that you are programming for only one model, or as close as it can manage, and not, for instance, pasting conditional boilerplate code to do simple things that are handled differently by different browser versions, often rendering surprisingly different interpretations of JavaScript. Many of the things we will see done well as we explore jQuery are also done well in other libraries.

We previously said that JavaScript is an excellent language and a terrible language rolled into one; what is to be said in favor of JavaScript? The list of faults is hardly all that is wrong with JavaScript, and saying that libraries can dull the pain is not itself a great compliment. But in fact, something much stronger can be said for JavaScript: If you can figure out why Python is a good language, you can figure out why JavaScript is a good language.

I remember, when I was chasing pointer errors in what became 60,000 lines of C, teasing a fellow student for using Perl instead of a real language. It was clear in my mind that there were interpreted scripting languages, such as the bash scripting that I used for minor convenience scripts, and then there were real languages, which were compiled to machine code. I was sure that a real language was identified with being compiled, among other things, and that power in a language was the sort of thing C traded in. (I wonder why he didn’t ask me if he wasn’t a real programmer because he didn’t spend half his time chasing pointer errors.) Within the past year or so I’ve been asked if “ Python is a real programming language or is just used for scripting,” and something similar to the attitude shift I needed to appreciate Perl and Python is needed to properly appreciate JavaScript.

The name “JavaScript” is unfortunate; like calling Python “Assembler Kit”, it’s a way to ask people not to see its real strengths. (Someone looking for tools for working on an assembler would be rather disgusted to buy an “Assembler Kit” and find Python inside. People looking for Java’s strengths in JavaScript will almost certainly be disappointed.)

JavaScript code may look like Java in an editor, but the resemblance is a façade; besides Mocha, which had been renamed LiveScript, being renamed to JavaScript just when Netscape was announcing Java support in web browsers, it is has been described as being descended from NewtonScript, Self, Smalltalk, and Lisp, as well as being influenced by Scheme, Perl, Python, C, and Java. What’s under the Java façade is pretty interesting. And, in the sense of the simplifying “façade” design pattern, JavaScript was marketed in a way almost guaranteed not to communicate its strengths to programmers. It was marketed as something that nontechnical people could add snippets of, in order to achieve minor, and usually annoying, effects on their web pages. It may not have been a toy language, but it sure was dressed up like one.

Python may not have functions clobbering each other’s variables (at least not unless they are explicitly declared global), but Python and JavaScript are both multiparadigm languages that support object-oriented programming, and their versions of “object-oriented” have a lot in common, particularly as compared to (for instance) Java. In Java, an object’s class defines its methods and the type of its fields, and this much is set in stone. In Python, an object’s class defines what an object starts off as, but methods and fields can be attached and detached at will. In JavaScript, classes as such do not exist (unless simulated by a library such as Prototype), but an object can inherit from another object, making a prototype and by implication a prototype chain, and like Python it is dynamic in that fields can be attached and detached at will. In Java, the instanceof keyword is important, as are class casts, associated with strong, static typing. Python doesn’t have casts, and its isinstance() function is seen by some as a mistake.

The concern is that Python, like JavaScript, is a duck-typing language: “If it looks like a duck, and it quacks like a duck, it’s a duck!” In a duck-typing language, if you write a program that polls weather data, and there’s a ForecastFromScreenscraper object that is several years old and screenscrapes an HTML page, you should be able to write a ForecastFromRSS object that gets the same information much more cleanly from an RSS feed. You should be able to use it as a drop-in replacement as long as you have the interface right. That is different from Java; at least if it were a ForecastFromScreenscraper object, code would break immediately if you handed it a ForecastFromRSS object. Now, in fairness to Java, the “best practices” Java way to do it would probably separate out an IForecast interface, which would be implemented by both ForecastFromScreenscraper and later ForecastFromRSS, and Java has ways of allowing drop-in replacements if they have been explicitly foreseen and planned for. However, in duck-typed languages, the reality goes beyond the fact that if the people in charge designed things carefully and used an interface for a particular role played by an object, you can make a drop-in replacement. In a duck-typed language, you can make a drop-in replacement for things that the original developers never imagined you would want to replace.

JavaScript’s reputation is changing. More and more people are recognizing that there’s more to the language than design flaws. More and more people are looking past the fact that JavaScript is packaged like Java, like packaging a hammer to give the impression that it is basically like a wrench. More and more people are looking past the silly “toy language” Halloween costume that JavaScript was stuffed into as a kid.

One of the ways good programmers grow is by learning new languages, and JavaScript is not just the gateway to mainstream Ajax; it is an interesting language in itself. With that much stated, we will be making a carefully chosen, selective use of JavaScript, and not make a language lover’s exploration of the JavaScript language, overall. Much of our work will be with the jQuery library; if you have just programmed a little “bare JavaScript”, discovering jQuery is a bit like discovering Python, in terms of a tool that cuts like a hot knife through butter. It takes learning, but it yields power and interesting results soon as well as having some room to grow.

What is XMLHttpRequest in relation to Ajax?

The XMLHttpRequest object is the reason why the kind of games that can be implemented with Ajax technologies do not stop at clones of Tetris and other games that do not know or care if they are attached to a network. They include massive multiplayer online role-playing games where the network is the computer. Without having something like XMLHttpRequest, “Ajax chess” would probably mean a game of chess against a chess engine running in your browser’s JavaScript engine; with XMLHttpRequest, “Ajax chess” is more likely man-to-man chess against another human player connected via the network. The XMLHttpRequest object is the object that lets Gmail, Google Maps, Bing Maps, Facebook, and many less famous Ajax applications deliver on Sun’s promise: the network is the computer.

There are differences and some incompatibilities between different versions of XMLHttpRequest, and efforts are underway to advance “level-2-compliant” XMLHttpRequest implementations, featuring everything that is expected of an XMLHttpRequest object today and providing further functionality in addition, somewhat in the spirit of level 2 or level 3 CSS compliance. We will not be looking at level 2 efforts, but we will look at the baseline of what is expected as standard in most XMLHttpRequest objects.

The basic way that an XMLHttpRequest object is used is that the object is created or reused (the preferred practice usually being to reuse rather than create and discard a large number), a callback event handler is specified, the connection is opened, the data is sent, and then when the network operation completes, the callback handler retrieves the response from XMLHttpRequest and takes an appropriate action.

A bare-bones XMLHttpRequest object can be expected to have the following methods and properties.