Today’s web applications often use remote scripting to communicate with the server without reloading the current page. This enables for much more responsive and desktop-like web applications. Let’s consider a few ways to communicate with the server from Javascript.
XMLHttpRequest
XMLHttpRequest
is a special object (a constructor function) available in most browsers today, which lets you make an HTTP request from Javascript. There are three steps to making a request:- Set up an
XMLHttpRequest
object (called XHR for short). - Provide a callback function to be notified when the request object changes state.
- Send the request.
The first step is as easy as:
var xhr = new XMLHttpRequest();
But in IE prior to version 7, the XHR functionality was implemented as an ActiveX object, so a special case is needed there.
The second step is providing a callback to the
readystatechange
event:xhr.onreadystatechange = handleResponse;
The last step is to fire off the request—using two methods
open()
and send()
. The open()
method sets up the HTTP request method (for example, GET, POST) and the URL. The send()
method passes any POST data or just a blank string in the case of GET. The last parameter to open()
specifies whether the request is asynchronous. Asynchronous means that the browser will not block waiting for the response. This is definitely the better user experience, so unless there’s a strong reason against it, the asynchronous parameter should always be true
:xhr.open("GET", "page.html", true); xhr.send();
Below is a complete working example of fetching the contents of a new page and updating the current page with the new content (demo available at http://jspatterns.com/book/8/xhr.html):
var i, xhr, activeXids = [ 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP' ]; if (typeof XMLHttpRequest === "function") { // native XHR xhr = new XMLHttpRequest(); } else { // IE before 7 for (i = 0; i < activeXids.length; i += 1) { try { xhr = new ActiveXObject(activeXids[i]); break; } catch (e) {} } } xhr.onreadystatechange = function () { if (xhr.readyState !== 4) { return false; } if (xhr.status !== 200) { alert("Error, status code: " + xhr.status); return false; } document.body.innerHTML += "<pre>" + xhr.responseText + "<\/pre>"; }; xhr.open("GET", "page.html", true); xhr.send("");
Some comments on the example:
- Because of IE versions 6 and below, the process of creating a new XHR object is a little more complicated. We loop through a list of ActiveX identifiers from the latest to the earliest version and attempt to create an object, wrapping it in a try-catch block.
- The callback function checks the
readyState
property of thexhr
object. There are five possible values of that property—from 0 to 4—where 4 means “complete.” If the state is not yet complete, we keep waiting for the nextreadystatechange
event. - The callback also checks the
status
property of thexhr
object. This property corresponds to the HTTP status code, for example, 200 (OK) or 404 (Not found). We’re only interested in the 200 response codes and report all others as errors (for simplicity; otherwise there are other valid status codes you could check for). - The code, as listed, will make a check for the supported way to create an XHR object every time a request is made. Having seen some patterns in previous chapters (for example, init-time branching), you could rewrite this to make the check only once.
JSONP
JSONP (JSON with padding) is another way to make remote requests. Unlike XHR, it’s not restricted by the same-domain browser policy, so it should be used carefully because of the security implications of loading data from third-party sites.
The response to an XHR request can be any type of document:
- XML documents (historically)
- HTML chunks (quite common)
- JSON data (lightweight and convenient)
- Simple text files and others
With JSONP the data is most often JSON wrapped in a function call, where the function name is provided with the request.
An example JSONP request URL would commonly look like this:
http://example.org/g...lback=myHandler
getdata.php could be any type of page or script. The
callback
parameter specifies which Javascript function will handle the response.The URL is then loaded into a dynamic
<script>
element, like so:var script = document.createElement("script"); script.src = url; document.body.appendChild(script);
The server responds with some JSON data passed as a parameter to the callback function. The end result is that you’ve actually included a new script in the page, which happens to be a function call. For example:
myHandler({"hello": "world"});
JSONP example: Tic-tac-toe
Let’s put the JSONP to work with an example—a game of tic-tac-toe, where the players are the client (the browser) and the server. Both will generate random numbers between 1 and 9, and we’ll use JSONP to get the value of the server’s turn (see
Figure 8-2
).You can play the game live at http://jspatterns.com/book/8/ttt.html.

There are two buttons: to start a new game and to get the server’s turn (the client’s turn will be automatic after a timeout):
<button id="new">New game</button> <button id="server">Server play</button>
The board will contain nine table cells with corresponding id attributes. For example:
<td id="cell-1"> </td> <td id="cell-2"> </td> <td id="cell-3"> </td> ...
The whole game is implemented in a
ttt
global object:var ttt = { // cells played so far played: [], // shorthand get: function (id) { return document.getElementById(id); }, // handle clicks setup: function () { this.get('new').onclick = this.newGame; this.get('server').onclick = this.remoteRequest; }, // clean the board newGame: function () { var tds = document.getElementsByTagName("td"), max = tds.length, i; for (i = 0; i < max; i += 1) { tds[i].innerHTML = " "; } ttt.played = []; }, // make a request remoteRequest: function () { var script = document.createElement("script"); script.src = "server.php?callback=ttt.serverPlay&played=" + ttt.played.join(','); document.body.appendChild(script); }, // callback, server's turn to play serverPlay: function (data) { if (data.error) { alert(data.error); return; } data = parseInt(data, 10); this.played.push(data); this.get('cell-' + data).innerHTML = '<span class="server">X<\/span>'; setTimeout(function () { ttt.clientPlay(); }, 300); // as if thinking hard }, // client's turn to play clientPlay: function () { var data = 5; if (this.played.length === 9) { alert("Game over"); return; } // keep coming up with random numbers 1-9 // until one not taken cell is found while (this.get('cell-' + data).innerHTML !== " ") { data = Math.ceil(Math.random() * 9); } this.get('cell-' + data).innerHTML = 'O'; this.played.push(data); } };
The object
ttt
maintains a list of cells played so far in ttt.played
and sends them to the server, so the server can return a new number excluding the ones that were already played. If an error occurs, the server will respond with output like:ttt.serverPlay({"error": "Error description here"});
As you can see, the callback in JSONP has to be a publicly and globally available function, not necessarily a global, but it can be a method of a global object. If there are no errors, the server will respond with a method call like:
ttt.serverPlay(3);
Here 3 means that cell number 3 is the server’s random choice. In this case the data is so simple that we don’t even need the JSON format; a single value is all it takes.
Frames and Image Beacons
An alternative way to do remote scripting is to use frames. With Javascript you can create an iframe and change its src URL. The new URL can contain data and function calls that update the caller—the parent page outside the iframe.
The simplest form of remote scripting is when all you need to do is to send data to the server, and you’re not expecting a response. In those cases you can create a new image and point its
src
to the script on the server:new Image().src = "http://example.org/some/page.php";
This pattern is called an image beacon and is useful when you want to send data to be logged by the server, for example for collecting visitor statistics. Because you have no use for a response of such a beacon, a common practice (but an antipattern) is to have the server respond with a 1×1 GIF image. A better option will be to respond with a “204 No Content” HTTP response. This means that only a header and no response body is sent back to the client.

What's the best approach for developing an application with Javascript? This book helps you answer that question with numerous Javascript coding patterns and best practices. If you're an experienced developer looking to solve problems related to objects, functions, inheritance, and other language-specific categories, the abstractions and code templates in this guide are ideal -- whether you're writing a client-side, server-side, or desktop application with Javascript. Author Stoyan Stefanov includes several examples for each pattern as well as practical advice for implementing them.

