Section A. Sending the request


A. Sending the request

Sending an HTTP request through the XMLHttpRequest object requires the following minimum steps:

1.

Create an XMLHttpRequest object (this is browser dependent).

2.

Instruct the object to open a specific file (the open() method).

3.

Tell the object what to do with the data the server will return (an onreadystatechange event handler).

4.

Give the object the command to send the request (the send() method).

There are more actions you can take, but we'll focus on these required steps first.

The XMLHttpRequest object

Warning

Browser incompatibilities ahead


In order to send an XMLHttpRequest request and receive a response, you first have to create an XMLHttpRequest object that's capable of performing these actions. Unfortunately, creating this object requires a few browser-dependent workarounds, since in Explorer 6 and earlier the object is an ActiveX object, while in all other browsers (including Explorer 7) it's a native object.

This is XMLHTTP Speed Meter's object-creation function:

[XMLHTTP Speed Meter, lines 140-145]

var XMLHttpFactories = [     function () {return new XMLHttpRequest()},     function () {return new ActiveXObject("Msxml2.XMLHTTP")},     function () {return new ActiveXObject("Msxml3.XMLHTTP")},     function () {return new ActiveXObject("Microsoft.XMLHTTP")} ]; 


First, we create an array, XMLHttpFactories, that contains one function for every possible way to create an XMLHttp object. The first one (new XMLHttpRequest()) tries to create a native object, while the remaining ones try to create ActiveX objects. Msxml2.XMLHTTP, Msxml3.XMLHTTP, and Microsoft.XMLHTTP are all possible names for that ActiveX object; which one is supported depends on the user's Windows configuration, not on the browser.

[XMLHTTP Speed Meter, lines 147-160]

function createXMLHTTPObject() {    var xmlhttp = false;    for (var i=0;i<XMLHttpFactories.length;i++) {            try{                   xmlhttp = XMLHttpFactories[i]();           }           catch (e) {                   continue;           }           break;     }     return xmlhttp; } 


The createXMLHTTPObject() function first sets the xmlhttp variable to false (no support). Then it goes through all factory methods and tries them. The problem is, of course, that if a factory method is not supported, executing it gives an error message.

Hence the use of a try/catch statement (see 5H). We try to execute each factory method. If that succeeds, we have an XMLHttpRequest object, the function skips the catch, and encounters the break that immediately ends the for loop. If a factory method gives an error, the function executes the catch statement and continues the for loop.

Afterwards, xmlhttp either refers to an XMLHttpRequest object that we can use, or it's still false, which means that the user's browser doesn't support XMLHttpRequest at all. We return this value to the function that asked for it.

The first time I call createXMLHTTPObject is during the overall object detection at the start of the script.

[XMLHTTP Speed Meter, lines 19-21]

[View full width]

window.onload = function () { var supportCheck = document.createElement && document.getElementsByTagName && createXMLHTTPObject(); if (!supportCheck) return;


The advanced interface should start up only if the browser supports both the W3C DOM and XMLHttpRequest. In addition to the normal W3C DOM check, the script tries to create an object. If that fails, the initialization function ends, and the user gets the noscript interface.

open

The next step is to open a new request, which means preparing it for sending. The actual send command is given later.

The basic syntax is as follows:

xmlhttp.open(method,url,true); 


method defines the method of the request: GET, POST, or HEAD. The first two work as always: With GET the (form) data is appended to the URL as a query string; with POST the data is sent along in the HTTP request's body.

A HEAD request returns only the HTTP headers of the response, not the file itself. This is occasionally useful, for instance if you want to display the last modification date of a file.

Posting Your Request

Note that if you want to POST your data you must set the 'Content-Type' header of the request to 'application/x-www-form-urlencoded'.


url is the URL of the file to be downloaded. The last argument tells the browser whether to handle the request asynchronously (true) or synchronously (false). You generally use true.

Practical example:

xmlhttp.open('GET','some.xml',true); 


Now the file some.xml is loaded by GET in an asynchronous way.

Asynchronous vs. Synchronous

Asynchronous means that the browser does not wait for the response, but immediately allows more JavaScript commands or user actions. In contrast, if you send a synchronous request, all browser activity is stalled until the response arrives.

The problem is, of course, that if all activity stalls, the browser stops responding to the user's actions. Especially when it takes more than a few seconds to download the data, the user may think that the browser has crashed, and this is something to be avoided at all costs. Therefore, synchronous requests are rarely useful.


readystatechange

After you've called the open() method, you should specify what happens when the response to your request arrives at the browser. For this you use the (originally Microsoft-proprietary) readystatechange event, which fires whenever the "ready state" of a request changes.

Personally, I'd rather use a simple load event ("when the response has loaded, do this"), but unfortunately Explorer doesn't support that event on XMLHttpRequests.

readystatechange is a curious event. There are five ready states: 0, 1, 2, 3, and 4.

Value

Meaning

Description

0

Uninitialized

The object has been created, but the open method has not yet been called.

1

Loading

The object has been created, but the send method has not yet been called.

2

Loaded

The send method has been called, but the status and headers are not yet available.

3

Interactive

Some data has been received.

4

Completed

All data has been received.


The first four values contain a few obscure browser incompatibilities and are very rarely used in practice. (I've never understood their purpose.) Ready state 4 (all data has been received) is the state generally used.

The basic syntax is as follows:

xmlhttp.onreadystatechange = function () {     if (xmlhttp.readyState != 4) return;     // do something with the response } 


When the ready state of the request changes, the handler fires. Its first point of action is seeing if readyState is 4. If it isn't, the function ends immediately. If it is, you can start doing something with the response. We'll get back to "doing something with the response" in 10B.

Oddities

Although onreadystatechange seems a normal event handler, there are some oddities. First of all, the event type is load in Explorer, instead of the readystatechange you'd expect. Secondly, only Safari creates an event object for this event. Therefore, the following code doesn't work:

   xmlhttp.onreadystatechange = handleResponse;  function handleResponse(e) {      var evt = e || window.event;      // now evt is only defined in Safari      // IE, Mozilla and Opera can't find the event object  } 


Fortunately, access to the event object is rarely necessary when using onreadystatechange.

send

Once you've called the open() method and set an onreadystatechange event handler, you can send the request. The syntax is as follows:

xmlhttp.send(data); 


The send() method requires an argument. If you POST your data, the argument is the post data; if you use GET, the argument is null.

When the request is sent, you wait for the response to arrive. When it arrives, the onreadystatechange event handler kicks in and does what you instructed it to do.

setRequestHeader

The four features we've discussed so far are required. There are two more methods of the XMLHttpRequest object that can come in handy in some situations.

Request Headers

You can find an overview of HTTP request headers at: http://www.w3.org/Protocols/HTTP/HTRQ_Headers.html.


The setRequestHeader() method allows you to set one of the HTTP request headers. Its syntax is as follows:

xmlhttp.setRequestHeader('Header-name','value'); 


I commonly set the User-Agent header to 'XMLHTTP' so that server-side programs are able to distinguish between XMLHttpRequests and other requests.

xmlhttp.setRequestHeader('User-Agent','XMLHTTP'); 


This allows you to write server-side scripts that serve up one document for advanced browsers and another one for browsers that don't support (sufficient) JavaScript. In 10D we'll see that this can occasionally be a useful accessibility tool.

If you want to POST your data, you must set another header:

req.setRequestHeader('Content-type','application/x-www-form-urlencoded'); 


sendRequest function

Let's bring all this wisdom together in one function: the sendRequest() function I use in all my XMLHttpRequest projects (including XMLHTTP Speed Meter). It requires the createXMLHTTPObject() function we discussed earlier.

[XMLHTTP Speed Meter, lines 120-138, condensed]

function sendRequest(url,callback,postData) {     var req = createXMLHTTPObject();     if (!req) return;     var method = (postData) ? "POST" : "GET";     req.open(method,url,true);     req.setRequestHeader('User-Agent','XMLHTTP');     if (postData)            req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');     req.onreadystatechange = function () {            if (req.readyState != 4) return;            if (req.status != 200 && req.status != 304) {                    alert('HTTP error ' + req.status);                    return;            }            callback(req);}     if (req.readyState == 4) return;     req.send(postData); } 


It's called like this:

sendRequest('some.xml',handleResponse); // GET sendRequest('some.xml',handleResponse,postData); // POST 


some.xml is the file you need, handleResponse is the function that should run when the response becomes available, and the optional argument postData contains the POST data.

First the function tries to create a new XMLHttpRequest object and store it in req. If that's not possible, the function ends. Otherwise, it checks if a postData argument exists: if so, it sets the request's method to POST; if not, it sets it to GET.

It opens the request with method, url, and true and sets the User-Agent header to 'XMLHTTP'. If the request should be POSTed, it sets the Content-type header to 'application/x-www-form-urlencoded'.

Then it creates an onreadystatechange event handler, which we'll discuss in the next section.

The function next checks if the request's readyState is already 4. If so, the document is already in the browser's cache, and the request does not need to be sent. This is important for Explorer, since if you request a file that's already cached in this browser, it may fire the onreadystatechange event handler before the request is officially sent, and that could cause weird problems.

Finally, the function sends the request with postData (either the POST data or null) as an argument.

abort

Warning

Browser incompatibilities ahead


The abort() method allows you to abort an ongoing request. This is rarely necessary. When you take an XMLHttpRequest object that's already downloading data and give it other instructions, it forgets about its previous orders and starts downloading the new data. The only exception to this rule is Mozilla: This browser may require you to use the abort() method first.

Note that if you use abort() you should first remove the onreadystatechange event handler, since Explorer and Mozilla also fire this event handler when the request is aborted:

xmlhttp.onreadystatechange = function () {}; xmlhttp.abort(); 


Note further that Explorer requires you to assign an empty function to onreadystatechange. If you give it a null value, weird errors ensue.



ppk on JavaScript. Modern, Accessible, Unobtrusive JavaScript Explained by Means of Eight Real-World Example Scripts2006
ppk on JavaScript. Modern, Accessible, Unobtrusive JavaScript Explained by Means of Eight Real-World Example Scripts2006
ISBN: N/A
EAN: N/A
Year: 2005
Pages: 116

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net