Learning about AJAX

What is AJAX?

AJAX (for Asynchronous JavaScript And XML) is a technique in which JavaScript (running in the browser) requests and receives data from a server asynchronously - in the background, without locking up the user interface. Compared to older approaches (where the only client/server interaction was the re-sending of entire web pages), this provides a much more responsive and interactive experience for the user. Despite the name, XML is not always used. In fact, JSON (JavaScript Object Notation) is often preferred because it is easier to use with JavaScript (you can just "eval" the JSON instead of having to parse the XML).

Click here to see what W3Schools has to say about AJAX.

Here is a very simple example of how to use JavaScript to make an AJAX call:

    
    var httpReq; // Declare the XMLHttpRequest Object globally so both functions can access it.
    if (window.XMLHttpRequest) {
        httpReq = new XMLHttpRequest();  //For Firefox, Safari, Opera
    } else if (window.ActiveXObject) {
        httpReq = new ActiveXObject("Microsoft.XMLHTTP");         //For IE 5+
    } else {
        alert('ajax not supported');
    }

    function sendRequest(artist) {  // Make the AJAX call (asynchronous, non-blocking)

        var call = "http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist="
                + artist + "&api_key=aff04cb3e4b21ab37d92659bdea550b1&format=json";
        httpReq.open("GET", call);
        httpReq.onreadystatechange = handleResponse; // specify the call back function
        httpReq.send(null);
    }

    function handleResponse() {  // This is the call back function
        if (httpReq.readyState == 4 && httpReq.status == 200) {
            var response = httpReq.responseText;
            var jsonObj = JSON.parse(response);
            if (jsonObj.artist == null) { // means artist not found.
                document.getElementById("bio").innerHTML = jsonObj.message;
            } else {
                document.getElementById("bio").innerHTML = jsonObj.artist.bio.summary;
            }
        }
    }   

Here is a better (more encapsulated) way to organize this code:

    function sendRequest(artist) {  // Make the AJAX call (asynchronous, non-blocking)

        var httpReq; // declared inside of sendRequest
        if (window.XMLHttpRequest) {
            httpReq = new XMLHttpRequest();  //For Firefox, Safari, Opera
        } else if (window.ActiveXObject) {
            httpReq = new ActiveXObject("Microsoft.XMLHTTP");         //For IE 5+
        } else {
            alert('ajax not supported');
        }
 
        var call = "http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist="
                + artist + "&api_key=aff04cb3e4b21ab37d92659bdea550b1&format=json";
        httpReq.open("GET", call);
        httpReq.onreadystatechange = handleResponse; // specify the call back function
        httpReq.send(null);

        // function handleResponse must also be declared inside of sendRequest so it can access httpReq.
        function handleResponse() {  // This is the call back function
            if (httpReq.readyState == 4 && httpReq.status == 200) {
                var response = httpReq.responseText;
                var jsonObj = JSON.parse(response);
                if (jsonObj.artist == null) { // means artist not found.
                    document.getElementById("bio").innerHTML = jsonObj.message;
                } else {
                    document.getElementById("bio").innerHTML = jsonObj.artist.bio.summary;
                }
            }
        }   
    }

Web Data Formats:

When you make an AJAX call, you get data back from a web server. This data would typically be in JSON or XML format (see examples below):

  • XML (Extensible Markup Language) was more popular at first - you can see that it looks like HTML but XML tag names are created by a programmer (instead of having a fixed, finite list of predefined tags, like HTML). The programmer can create a DTD (Document Type Definition) which can be used to validate an XML document - to see if it is well formed or not.
  • Now, JSON (JavaScript Object Notation) is typically preferred because it is very convenient to convert JSON to a JavaScript object - all you have to do is run the server response through the JSON.parse( ) function.

Demonstration of JavaScript Object Notation (JSON).

How do I debug AJAX?

AJAX errors can often be a result of your not understanding the exact structure of the JSON string that you are trying to parse. To learn more about the structure of the JSON string, type the URL (of the ajax call) into the browser's address bar and hit enter. If you see a page full of characters, you know your call got a response from the Web API. To make sense of the data, make sure that you have installed the "JSON Viewer" plugin to Chrome. Google for this, or click here. After installing the JSON Viewer plugin, you should be able to refresh the page that holds the JSON string and you'll see it nicely formatted.

Since AJAX is just a technique that uses JavaScript (or jQuery, a JavaScript library), use the Chrome debugger (F12, click on consol), just like you do for any JavaScript.

What is a CORS Error?

As you experiment with making AJAX calls to third party web sites, you may see this CORS error (Cross Origin Resource Sharing) from the Chrome debugger's console tab:

No 'Access-Control-Allow-Origin' header is present on the requested resource

When the domain of an HTML page is different than the domain of the Web API that it is calling, the CORS error indicates a potential security risk (e.g., that a page might be running some injected JavaScript code). You can install a CORS plugin (to your Chrome browser) to make your browser willing to share data with another domain, but the problem will only be resolved if the Web API is also willing to accept AJAX calls from other domains. Also, if you needed a CORS plugin to run a Web API while developing locally, it is likely that you will get the CORS error again once you publish your page (and you have no control over cis-linux2 security settings). So, test early (to see if your published AJAX page will get a CORS error), before you spend too much time perfecting your code. If you get a CORS error, you should probably give up on that Web API and look for another.

Calling an Anime Web API

The Anime Web API provides information (episode summaries and images) about Anime characters. If you do not know much about Anime (like I don't), several Anime character names have been placed on the page to help you test out the page. There is also a link that provides a long list of Anime characters for you to play with, if interested. While most Web API services require that you set up an account (free or paid) so you can get a Web API key (that you must provide with each Web API call), the Anime Web API does not require any Web API key - which is one of the reasons why I picked this API to demonstrate to you.

This is an example URL that invokes a Web API (to an Anime service that provides information based on the name of a particular Anime character). If the output looks unformatted, make sure to install the "JSON View" for Chrome plugin into your browser.

This version shows a plain JavaScript AJAX call to the Anime Web API. This rudimentary code declares a global http request object that can be accessed by two global functions (one to make the asynchronous call and one to handle the response).

In this version, there is only one global function (sendRequest) which declares the http request object locally and also defines a local handleResponse function. This shows better encapsulation, but still not as reusable as we would like because all the code is still in the HTML file.

This version moves the reusable code to an external JS file. Because the function in the JS file makes no assumptions about the HTML page (other than what is passed to it), we can say this version uses "dependency injection", a very good software design goal.

In this version, multiple results are extracted from the Web API response.

This version is functionally the same as the previous version (extracts multiple results from the Web API response), but it uses jQuery instead of plain JavaScript.

Calling Google Map Web API

JavaScript AJAX call to Google Maps: Location is Philadelphia. I made the map size less than 100% of the browser screen, so you can right click and View Source.

Calling YouTube Web API

This code was calling YouTube Search (using AJAX/JavaScript) and it used to work until they changed things on their end (a risk you take when you write a web app that depends on a 3rd party Web API provider). Click here for a 12 minute video that tells you how to get this working (starting with signing up for a Web API key).

Explaining Callback Functions

When you write provider code (which I often refer to as "framework style coding"), consumer code may pass a function to the provider so that the provider will execute the function upon some (mutually agreed) conditions. This function (passed by consumer to provider) is called a "call back" function.

To demonstrate a simple/silly "call back" function, I have prepared this example (see two grey boxes below). The consumer code passes two functions to the provider - functions arbitrarily named "leftFunc" and "rightFunc". Each time the provider code (callBackFunc, see below) is called, it arbitrarily invokes either leftFunc or rightFunc. Note that leftFunc expects an input parameter (passed by the provider to the consumer), whereas rightFunc does not expect any inputs. Note that the callback functions (leftFunc and right Func) actually exist in the consumer code, but by passing these function references to the provider, the consumer code "gives permission" to the provider code to run the functions.

Provider Code (stored in callBackFunc.js, an external JS file)

    function callBackFunc (leftFunc, rightFunc) {

        function makeRandomNumber(low, high) { // returns an integer in this range: low..high
            var random = Math.random();  
            var diff = high - low + 1;  
            return Math.floor(random * diff + low);
        }

        var random = makeRandomNumber(1, 100);

        if (random <= 50) {
            leftFunc("Your magic number was "+random);
        } else {
            rightFunc();
        }
    }       

Consumer Code (JS of the HTML page)

    <script src='callBackFunc.js'></script>
    <script>

        function myLeftFunc(inputParam) {
            console.log("myLeftFunc was invoked with this input: " + inputParam);
        }

        function myRightFunc() {
            console.log("myRightFunc was invoked (no input supplied)");
        }
        for (var i = 0; i < 6; i++) {
            callBackFunc(myLeftFunc, myRightFunc);
        }

    </script>        

Click here to run the above code sample.

Click here for zip file of all the ajax examples on this page.