Ajax.Request

new Ajax.Request(url[, options]) Initiates and processes an AJAX request.

This object is a general-purpose AJAX requester: it handles the life-cycle of the request, handles the boilerplate, and lets you plug in callback functions for your custom needs.

In the optional options hash, you usually provide a onComplete and/or onSuccess callback, unless you're in the edge case where you're getting a Javascript-typed response, that will automatically be eval'd.

For a full list of common options and callbacks, see Ajax Options.

The only proper way to create a requester is through the new operator. As soon as the object is created, it initiates the request, then goes on processing it throughout its life-cycle.

A basic example

URL = 'http://www.google.com/search?q=Prototype';

new Ajax.Request('/proxy?url=' + encodeURIComponent(URL), {

method: 'get',

onSuccess: function(transport) {

var notice = $('notice');

if (transport.responseText.match(/<a class=l href="http:\/\/prototypejs.org/))

notice.update('Yeah! You are in the Top 10!').setStyle({ background: '#dfd' });

else

notice.update('Damn! You are beyond #10...').setStyle({ background: '#fdd' });

}

});

Request life-cycle

Underneath our nice requester objects lies, of course, XMLHttpRequest. The defined life-cycle is as follows:

1. Created

2. Initialized

3. Request sent

4. Response being received (can occur many times, as packets come in)

5. Response received, request complete

As you can see in Ajax options, Prototype's AJAX objects define a whole slew of callbacks,

which are triggered in the following order:

1. onCreate (this is actually a callback reserved to AJAX global responders)

2. onUninitialized (maps on Created)

3. onLoading (maps on Initialized)

4. onLoaded (maps on Request sent)

5. onInteractive (maps on Response being received)

6. onXYZ (numerical response status code), onSuccess or onFailure (see below)

7. onComplete

The two last steps both map on Response received, in that order. If a status-specific callback is defined, it gets invoked. Otherwise, if onSuccess is defined and the response is deemed a success (see below), it is invoked. Otherwise, if onFailure is defined and the response is not deemed a success, it is invoked. Only after that potential first callback is onComplete called.

A note on portability

Depending on how your browser implements XMLHttpRequest, one or more callbacks may never be invoked. In particular, onLoaded and onInteractive are not a 100% safe bet so far. However, the global onCreate, onUninitialized and the two final steps are very much guaranteed.

onSuccess and onFailure, the under-used callbacks

Way too many people use Ajax.Requester in a similar manner to raw XHR, defining only an onComplete callback even when they're only interested in "successful" responses, thereby testing it by hand:

// This is too bad, there's better!

new Ajax.Requester('/your/url', {

onComplete: function(transport) {

if (200 == transport.status)

// yada yada yada

}

});

First, as described below, you could use better "success" detection: success is generally defined, HTTP-wise, as either no response status or a "2xy" response status (e.g., 201 is a success, too). See the example below.

Second, you could dispense with status testing altogether! Prototype adds callbacks specific to success and failure, which we listed above. Here's what you could do if you're only interested in success, for instance:

new Ajax.Requester('/your/url', {

onSuccess: function(transport) {

// yada yada yada

}

});

Automatic JavaScript response evaluation

Any response whose MIME type is missing or JavaScript-related will automatically be passed to eval. Before yelling on what a security breach that is, remember that XHR is usually used on URLs from the same host that originated the current page (this is the famous Same Origin Policy, or SOP): these scripts are supposed to be under your control.

What this means is, you don't even need to provide a callback to leverage pure-JavaScript AJAX responses. That's pretty cool, wouldn't you say? The list of JavaScript-related MIME types handled by Prototype is:

· | application/ecmascript

· | application/javascript

· | application/x-ecmascript

· | application/x-javascript

· | text/ecmascript

· | text/javascript

· | text/x-ecmascript

· | text/x-javascript

The MIME type string is examined in a case-insensitive manner.

Methods you may find useful

Requester objects provide several methods that can come in handy in your callback functions, especially once the request completed. Since alllocal callbacks execute in the requester's context, you're able to use these methods in your callback code.

Is the response a successful one?

The success() method examines the XHR's status property, and follows general HTTP guidelines: unknown status is deemed successful, as is the whole 2xy status code family. It's a generally better way of testing your response than the usual 200 == transport.status.

Getting HTTP response headers

While you can obtain response headers from the XHR object, using its getResponseHeader method, this makes for slightly verbose code, and several implementations may raise an exception when the header is not found. To make this easier, you can use the getHeader method, which just delegates to the longer version and returns null should an exception occur:

new Ajax.Requester('/your/url', {

onSuccess: function() {

// Note how we brace against null values

if ((this.getHeader('Server') || '').match(/Apache/))

++gApacheCount;

// Remainder of the code

}

});

Evaluating JSON headers

Some backends will return JSON not as response text, but in the X-JSON header. You can directly eval its content and get the result by calling the evalJSON method, which returns null if there is no such header, or the contents is invalid. For robustness, the header's content is wrapped in parentheses prior to evaluat ion.

You actually don't even need to call this method yourself, as Prototype automatically calls it and passes the result as the final argument to any callback (except for onCreate). So the following code is suboptimal:

new Ajax.Request('/your/url', {

onSuccess: function() {

var json = this.evalJSON(); // Uselessly evals a second time!

// Remainder of the code

}

});

Prefer the following approach:

new Ajax.Request('/your/url', {

onSuccess: function(transport, json) {

// Remainder of the code

}

});

Prototype API 1.5.0 - prototypejs.org