Tutorial 4: Asynchronous Server Requests

This tutorial will teach you how to fetch data from the server. Knowledge of how to access the DOM from JavaScript is assumed. There are five short lessons, followed by one exercise.

It is highly recommended that you open your browser's JavaScript console now. When stuff doesn't work, there's usually an error printed in the console. The console is your friend.

Lesson 1: XMLHttpRequest

Fetching new data from the server without reloading the page makes web applications much faster and more responsive. On this server there is a file called data.txt. Let's fetch the contents of this file with JavaScript.

Here is the skeleton for an XMLHttpRequest[?] call:

var sendAjax = function() {
  var req = new XMLHttpRequest();Create a new XMLHttpRequest object.
  req.open('GET', 'data.txt');Configure the XMLHttpRequest object.
Use GET or POST, and set the relative URL.
req.onreadystatechange = myResponseHandler;When the response comes back from the server,
call this function. 'this' will be the XMLHttpRequest object.
req.send();Actually send the request. }; document.getElementById('execute1').addEventListener('click', sendAjax, false);When the button is clicked,
send the AJAX request.

Mouse over each of the above lines to see what's happening.

Write some JavaScript code below that defines myResponseHandler as a function that simply alerts this.responseText. Then click the 'Execute' button.


 

Sample solution
Multiple alerts are OK! The next lesson will explain why.
var myResponseHandler = function() {
  alert(this.responseText);
};

Lesson 2: readyState & status

The previous lesson resulted in three alerts. That's because the response handler was called at three different stages of the request:

  1. The connection is about to be made.
  2. Data has started to arrive from the connection.
  3. All data has been received.

Most response handlers only care about the final state (4). Therefore your response handler should only alert if the XMLHttpRequest object's readyState property is 4.

Likewise, your response handler should also check that the page loaded correctly with an HTTP code of 200. Sometimes the server will fail, return an HTTP code of 500, and you don't want your handler attempting to parse some random Python stack trace instead of data. Therefore your response handler should also only alert if the XMLHttpRequest object's status property is 200.

Write some JavaScript code below that defines myResponseHandler as a function that alerts this.responseText only if this.readyState and this.status have the correct values. (In the context of a response handler, this is the XMLHttpRequest object.) Then click the 'Execute' button.


 

Sample solution
var myResponseHandler = function() {
  if (this.readyState == 4 && this.status == 200) {
    alert(this.responseText);
  }
};

Lesson 3: XML

As implied by the name, XMLHttpRequest is often used to request XML from the server. The code in previous lessons can fetch XML, but it would arrive as text, leaving you to write a parser. A better way is to use the responseXML property instead of the responseText property. Then the contents of the responseXML property will contain a fully-parsed DOM tree.

var sendAjax = function() {
  var req = new XMLHttpRequest();
  req.open('GET', 'data.xml');
  req.onreadystatechange = myResponseHandler;
  req.send();
};
document.getElementById('execute3').addEventListener('click', sendAjax, false);

On this server there is a file called data.xml. Write some JavaScript code below that defines myResponseHandler as a function that fetches this data, finds the first cat using this.responseXML.getElementsByTagName, and alerts its name.


 

Sample solution
var myResponseHandler = function() {
  if (this.readyState == 4 && this.status == 200) {
    alert(this.responseXML.getElementsByTagName('cat')[0].getAttribute('name'));
  }
};

Lesson 4: JSON

In addition to text and XML, JSON[?] is an extremely common data type. Parsing JSON is easy, just get the data as text and pass it to JSON.parse().

var sendAjax = function() {
  var req = new XMLHttpRequest();
  req.open('GET', 'data.json');
  req.onreadystatechange = myResponseHandler;
  req.send();
};
document.getElementById('execute4').addEventListener('click', sendAjax, false);

On this server there is a file called data.json. Write some JavaScript code below that defines myResponseHandler as a function that fetches this data, finds the first astronaut to walk on the moon, and alerts his name.


 

Sample solution
var myResponseHandler = function() {
  if (this.readyState == 4 && this.status == 200) {
    alert(JSON.parse(this.responseText).apollo11[0]);
  }
};

Lesson 5: Sending data

Previous lessons have demonstrated how to receive data from the server, but what about sending data to the server? The simplest way to do this is to use the GET method to append data to the URL.

This server hosts a simple calculator. This link demonstrates the addition of two numbers: /add.py?a=4&b=8

Modify the JavaScript code below so that the numbers in the following two input fields (with IDs "number1" and "number2" respectively) are added together and the number alerted. The contents of an input field may be obtained from its value property.

+


 

Sample solution
var req = new XMLHttpRequest();
var a = document.getElementById('number1').value;
var b = document.getElementById('number2').value;
req.open('GET', '/add.py?a=' + a + '&b=' + b);
req.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      alert(this.responseText);
    }
  };
req.send();

Exercise: Collaborative Stars

The goal of this exercise is to write a collaborative drawing application where users can turn stars on and off and all other viewers of this page see the same pattern.

  1. Add an event handler to each star (or to the table) so that when a star is clicked it toggles between on and off.
  2. Send the clicked star's number (0-99) and new state (0 or 1) to the server in this format: /collab.py?n=99&s=1
  3. The resulting response is a 100 character string that should be used to turn on or off each of the 100 stars.

Work through each step, one by one. When complete, you may wish to open another copy of this page in another window to verify that collaboration is occurring.

Here is a table containing 100 stars:

This is the HTML for the table to the left:

<table id="star_table">
  <tr>
    <td><img id="star_0" src="star_off.gif"><td>
    <td><img id="star_1" src="star_off.gif"><td>
    <td><img id="star_2" src="star_off.gif"><td>
    ...
  <tr>
  </tr>
    <td><img id="star_10" src="star_off.gif"><td>
    <td><img id="star_11" src="star_off.gif"><td>
    <td><img id="star_12" src="star_off.gif"><td>
    ...
  <tr>
  ...
</table>


Bonus #1: The 'GET' protocol should not be used to change server state, which is what is happening here. Convert the XMLHttpRequest to use 'POST'. See: Using POST method in XMLHttpRequest.

Bonus #2: Updates only happen when the user clicks a star. Try creating a recurring task with window.setInterval[?] that sends a request to /collab.py with no arguments to get an update.

Use the Intro to JavaScript forum to share your solution to this exercise and see other people's solutions.