AJAX The Mighty: The Rise of Web Applications
TIME LIMIT: 45 minutes
Time to talk about the magic of AJAX, i.e. asynchronous JavaScript, the networking technology behind the fetch
and $.getJSON
functions you used to import your JSON data in the two previous chapters.
In brief: AJAX is the ability to use HTTP in the background of a webpage. This means that a browser can request and receive fresh data (JSON) from a server without having to reload all of the user interface (HTML/CSS/JS) code. This technology makes webpages much faster (and more modular), which in turn has allowed for more sophisticated user interfaces. AJAX is how a front-end web application communicates with its backend (as we will see in several chapters).
AJAX is integral to the rise of web applications as alternatives to desktop (“native”) applications. The implications for consumer software have been enormous. With the rise of cloud computing and broadband internet, web applications have become the primary mode of consumer software delivery.
Let’s look at an example of AJAX in action.
Asynchronous I/O on Webpages
Have you ever wondered how search engines are able to show you predictions before you hit ENTER
?
DuckDuckGo is using AJAX. As you type, the DDG webpage uses JavaScript to make HTTP requests to an external server without having to reload the whole page. Open up the Network developer tool while you’re typing, and you will see those requests and responses fly!
Pay particular attention to that Request URL. The DuckDuckGo webpage is sending an HTTP GET request to its backend server, saying “Hey, API endpoint at the /ac
path! Give me predictions for the search string ‘asynchronous+J’”
If you click into the HTTP Response, you will find an array of response objects.
[
{"phrase":"asynchronous javascript"},
{"phrase":"asynchronous java"},
{"phrase":"asynchronous js"},
...
]
If you are thinking “Geez, y’all, this seems pretty similar to what we’ve been doing” – you’re right! If you were to use the previous two chapters as crib sheets, you could probably figure it out. If we were to make a webpage like the DuckDuckGo homepage, we would begin by creating the HTML and then making JavaScript that did something like this:
- Create reference to search input DOM node.
- Create event listener on that node - listen for keydown events.
- When keydown occurs, extract current search input text.
- Send HTTP Request to
/ac
URL endpoint withq=<text>
query parameter. - If successful HTTP Response received, parse JSON from the HTTP body.
- Iterate over search prediction JSON.
- For each search prediction, (1) create DOM node, and (2) attach to DOM.
In the beginning, it wasn’t this easy.
The History of Asynchronous JavaScript
The Problem: Slow Webpages With Little Interactivity
In the 90s, it was obvious that the Internet had tremendous potential, but webpage applications were slower than desktop (native) applications. Native applications did not have to reload all of their UI code every time they communicated with an external server.
The problem was this: User interactivity was very expensive. Anytime a user needed to take an action that required your code to communicate with a server, you had to reload the entire webpage. All HTML, CSS, JavaScript and data had to be wrapped up into one complete package. For every user interaction that required communication with an external server, the browser reloaded the same assets over and over and over. Even if only a few characters of text on the page changed! User interactivity was clunky and slow. It was computationally and practically inefficient.
It was frustrating and slow for users. If the computer had already loaded all of the code 2 minutes ago, why did we have to re-load it every time? Why would you need to re-download a company’s logo for every single page interaction? Why did the webpage make you wait for 12 seconds just to tell you there was no “@” symbol in your email?
The browser’s need for a data exchange layer that could run without altering the UI was clear.
Enter XMLHttpRequest
: The original JavaScript interface for HTTP
By 2005, all of the browsers had implemented a Web API called XMLHttpRequest
and it became the de facto standard for making asynchronous HTTP requests.
To use it, you instantiate an instance of the object (you might want to make multiple HTTP requests, so you want a separate instance for each request). Once instantiated, you have access to a wide array of methods that can be used to configure and make the request. You also register a callback function that handles the eventual HTTP response.
The object is still available for your use (browsers place great emphasis on backwards compatibility). If you navigate to DuckDuckGo.com and open up your JavaScript console, you can GET the search predictions from their backend API yourself!
var XHR = new XMLHttpRequest();
function callback(response) {
console.log(response.responseText);
}
XHR.addEventListener("load", callback);
XHR.open("GET", "https://duckduckgo.com/ac/?q=asynchronous+j");
XHR.send();
Google launched Gmail in 2005, to great fanfare. That same year, the term “AJAX” gained widespread use. It originally stood for “Asynchronous JavaScript and XML”. XML was the predominant data format that people sent around with HTTP at that time. Shortly after the term AJAX came to prominence, the JSON format overtook XML in popularity, but the term stuck.
As a fan of The Iliad, I like to think that it stuck because it’s also the name of a hero, Ajax the Great. AJAX is the technological hero that took browser applications to greater heights.
jQuery Comes To The Table: $.ajax
The jQuery DOM manipulation library launched at the end of 2005 and announced support for asynchronous JavaScript with the $.ajax
API in early 2006. You can send the same endpoint request as above with the following code:
const httpRequestSettings = {
dataType: "json",
url: "https://duckduckgo.com/ac/?q=asynchronous+j",
method: "get",
success: function(response) {
console.dir(response);
}
};
$.ajax(httpRequestSettings);
This is a more elegant interface than XMLHttpRequest
, but the similarities are there. The success
settings above is a callback function (that is called with the Response object).
jQuery has also made a few shorthand methods for the most common configuration settings. For example, in the previous chapter, we used $.getJSON
. We could have rewritten the above code as
const callback = function(response) {
console.dir(response);
};
$.getJSON("https://duckduckgo.com/ac/?q=asynchronous+j", callback);
You begin to see where jQuery’s “Write Less, Do More” motto came from. However, we are not done abstracting away from raw HTTP messages into ever-more-helpful interfaces just yet.
Fetch - Modern browsers launch a friendlier API
When the ES6 version of JavaScript came out, it debuted a new feature called promises. Promises represent asynchronous functions. You initially call fetch
with a URL, then it returns an object with then
methods on it. When your asynchronous code has finished execution, you can begin method chaining with then. Each then
method takes one argument: A function that takes the return value of the previous method as its argument. Thus you can create pipelines for processing of Response object data. There is also a handy catch
method you should always chain to the end to deal with errors.
fetch("https://duckduckgo.com/ac/?q=asynchronous+j")
.then(function(response) {
if (!response.ok) {
throw Error(response.statusText);
}
// Read the response as json.
return response.json();
})
.then(function(responseAsJson) {
console.dir(responseAsJson);
})
.catch(function(error) {
console.log('Looks like there was a problem: \n', error);
});
The fetch
interface is fairly slick. We’ve come a long way since XMLHttpRequest
!
Recap
The World Wide Web runs on HTTP, and AJAX has become a buzzword. We have just looked at three of the most popular ways programmers used AJAX over the last several decades.
As a developer, the most important thing to remember about AJAX and HTTP is that there is always a Request and Response. As a developer of sophisticated web applications, you will find yourself using them often.
Exercises
- History is a valuable instructor. Reading about how others have hacked their way to new user functionalities will teach you patterns you can repeat in the future.
- Ajax: A New Approach to Web Applications by Jesse James Garrett, 2005. http://adaptivepath.org/ideas/ajax-new-approach-web-applications/
- A Brief History of AJAX by Aaron Swartz, 2005. http://www.aaronsw.com/weblog/ajaxhistory
- Browse the jQuery documentation about AJAX. How many shorthand methods for making AJAX requests are there?
https://api.jquery.com/category/ajax/
-
AJAX made it much easier to write CRUD applications on the web. Go read the Wikipedia page for CRUD apps; they’re a popular topic in interviews. https://en.wikipedia.org/wiki/Create,_read,_update_and_delete
- Be ready to toss around the following buzzwords:
- HTTP request
- HTTP response
- presentation layer
- data interchange
- asynchronous i/o
- concurrency
- event loop
- networking
- Request bloat Just because a webpage can make 100 HTTP requests a minute does not mean that it should. Before you separate an application into 100 files, think about whether you should do that. It’s generally best to start with 1 file, and then separate your concerns into other files (modules) of code that need to be imported.