Overview
JavaScript's XMLHttpRequest
enables the responsive,
persistent user interfaces that characterize AJAX applications. Web
applications can use XMLHttpRequest
to communicate with
the server from JavaScript without reloading the page or blocking.
But while most modern browsers support XMLHttpRequest
,
different browsers have different implementations. To make sure your
app has the same behavior for each browser, you have to do extra work.
You can smooth over these browser differences by using the Closure
Library's XhrIo
class. XhrIo
also adds the
ability to set timeouts, and handles all notification for
both readyState changes and timeouts with a single set of
informative event types.
This document first introduces XhrIo with a quick example, then describes in greater detail the process of sending a query, monitoring its status, and processing its results.
Quick Examples
There are two ways to send an asynchronous request
with XhrIo
: by calling the
the goog.net.XhrIo.send()
utility function, and by
instantiating goog.net.XhrIo
and calling the
instance's send()
method.
send() Utility Function Example
The Closure Library provides a simple utility function for the common use case of one-off requests. The following example illustrates its use.
[ xhr-quick.js ]
goog.require('goog.net.XhrIo'); /** * Retrieve JSON data using XhrIo's static send() method. * * @param {string} dataUrl The url to request. */ function getData(dataUrl) { log('Sending simple request for ['+ dataUrl + ']'); goog.net.XhrIo.send(dataUrl, function(e) { var xhr = e.target; var obj = xhr.getResponseJson(); log('Received Json data object with title property of "' + obj['title'] + '"'); alert(obj['content']); }); } function log(msg) { document.getElementById('log').appendChild(document.createTextNode(msg)); document.getElementById('log').appendChild(document.createElement('br')); }
The call to goog.net.XhrIo.send()
above passes two arguments:
- The URL to request.
- A function to call when the response is
received. In the context of this callback function, the keyword
this
refers to anXhrIo
instance holding the result. We use thegetResponseJson()
method of this instance to evaluate the response as JSON and retrieve the resulting JavaScript object.
In the example
HTML page this function is registered as an onload
handler:
<body onload="getData('xhrio_data.json')">
When the document loads, getData()
sends an asynchronous
network request for
xhrio_data.json
. Note that in this simple example the
response is just a static file served by the web server; in a real web
application the server might generate this response
dynamically. In this case, the file we're requesting looks like this:
{ "title": "My JSON Data", "content": "What's mine is yours." }
This text consists of proper JavaScript syntax for an object literal
(i.e., JavaScript Object Notation or JSON), so we retrieve the
response as a JavaScript object using the
getResponseJson()
method. You can also retrieve and parse
XML, or you can simply get the raw text of the response, as described
in Retrieving Request Results.
send() Instance Method Example
You can also send a request by creating a new XhrIo
instance, adding an event listener,
and calling the send()
method on the instance:
[ xhr-quick2.js ]
goog.require('goog.net.XhrIo'); var xhr = new goog.net.XhrIo(); goog.events.listen(xhr, goog.net.EventType.COMPLETE, function(e) { obj = this.getResponseJson(); log('Received Json data object with title property of "' + obj['title'] + '"'); alert(obj['content']); }); function getData(dataUrl) { log('Sending simple request for ['+ dataUrl + ']'); xhr.send(dataUrl); }
Sending and Monitoring a Request Using XhrIo
The examples above illustrate the two ways to send a request
with XhrIo
: the send()
utility function and
the send()
instance method. These two approaches have
advantages and disadvantages:
- The
send()
utility function- Pros: simple
- Cons: limited, inefficient
- The
send()
instance method- Pros: flexible, allows reuse of
XhrIo
instances - Cons: takes more steps to set up
- Pros: flexible, allows reuse of
The following sections discuss each of these two approaches in greater detail.
Using XhrIo's send() Utility Function
The utility function XhrIo.send()
provides a way to make an
asynchronous request with a single call. It takes an optional callback
parameter, and this callback is called once whenever
the request has been resolved or has been determined to have failed for
any reason (HTTP error, timeout, etc.). The complete signature
for XhrIo.send()
is:
goog.net.XhrIo.send(url, opt_callback, opt_method, opt_content, opt_headers, opt_timeoutInterval)
- url
The URL to which you want to send the HTTP request. This can be a string or an instance of
goog.Uri
.- opt_callback
The function to be called when the request has been completed. The callback is passed an event object representing the request completion, and the target property of this event object points to the
XhrIo
object used to send the request.- opt_method
The HTTP method of the request (usually either "POST" or "GET"). Defaults to "GET".
- opt_content
The data to be posted for POST requests.
- opt_headers
A map of key-value pairs to be added to the HTTP request as headers. Either a plain JavaScript
Object
or agoog.structs.Map
.- opt_timeoutInterval
The number of milliseconds after which an incomplete request will be aborted. A value of 0 prevents a timeout from being set, in which case the request is governed by the browser's timeout (which is usually 30 seconds).
XhrIo.send()
sends its request by creating
an XhrIo
instance. It attaches an event listener to
the XhrIo
to listen for request completion. It also
attaches a listener that automatically disposes of
the XhrIo
after the completion message has been
dispatched. Note that XhrIo.send()
creates a
new XhrIo
instance for every request.
When the request completes, the callback function is passed an event
object representing the completion. The target property of
this object refers to the XhrIo
instance used to execute
the request. You can use this target property to retrieve
information from the XhrIo
instance.
For example, if your callback parameter is called e, in
your callback function you can
call e.target.isSuccess()
, e.target.getResponseText()
,
or any of the other instance methods of XhrIo
. When you
use the static send()
method you don't have the
opportunity to attach your own event handlers to its
short-lived XhrIo
instance. The opt_callback
parameter is the only vehicle for notification available to you, and
it is only called for 'complete' events (which will be fired for both
successfully completed and aborted requests).
Using XhrIo's send() Instance Method
XhrIo
's send()
instance method provides a
wider and more flexible interface than the utility function. Instead
of a single callback function, this approach uses event listeners to
get information about the status of the request.
To send a request using the send()
instance
method:
- Create or acquire an
XhrIo
instance. - Attach event listeners to the instance to monitor the request and process its results.
- Optionally set a timeout interval.
- Send requests by calling the instance's
send()
method.
Creating or Acquiring an XhrIo Instance
The constructor XhrIo()
does not take any parameters. You
define a request by passing parameters to the
instance's send()
method rather than through constructor
parameters.
Using goog.net.XhrIoPool
If you need to submit multiple requests simultaneously, consider using
an instance
of goog.net.XhrIoPool
. XhrIoPool
maintains a pool
of XhrIo
instances, supplying an instance on request if
one is available (that is, if there is an instance in the pool that is
not currently processing a request).
To complete signature of the XhrIoPool
constructor is:
new goog.net.XhrIoPool(opt_headers, opt_minCount, opt_maxCount)
- opt_headers
- A map of HTTP header name/value pairs to add to every request sent with an XhrIo instance from the pool.
- opt_minCount
- The minimum number of XhrIo instances to keep in the pool at all times (defaults to 1).
- opt_maxCount
- The
maximum number of
XhrIo
instances (defaults to 10).
To get an XhrIo
instance from the pool, call
getObject(opt_callback, opt_priority)
where opt_callback
is a callback function that is called
when an XhrIo
instance becomes available (with the
instance passed as the parameter to the callback),
and opt_priority
is a number that determines which
requests get fulfilled first if there is a shortage of instances in
the pool (lower numbers indicating higher priority). If you
omit opt_callback
, an instance is returned if one is
available, and undefined
is returned if no instance is
available.
When you are done using an XhrIo
instance from a pool,
call the pool's releaseObject(obj)
method
(where obj
is the XhrIo
instance) to return
the instance to the pool so that it can be reused.
In addition to the queuing facilities provided
by XhrIoPool
, the Closure Library also
provides more sophisticated connection management
through goog.net.XhrManager
.
XhrManager
uses an XhrIoPool
instance, but
enhances the basic pool with automatic retries and aggregate event
handling. Its use is beyond the scope of this document, but you might
find it helpful if you need advanced connection management
capabilities.
Handling Request Events
Listening for Request Events
Attach event listeners to the XhrIo
instance to monitor
request status and process request results. XhrIo
listens
for the native readystatechange
events, performs the
required lookup and interpretation of the readyState, and
then dispatches its own events.
XhrIo
dispatches the following types of events:
Event type constant | When event is dispatched |
---|---|
goog.net.EventType.READY_STATE_CHANGE
| Dispatched on any change to the ready
state. In other words, fired in response to any native
browser readystatechange event. |
goog.net.EventType.COMPLETE |
Dispatched when the request has been resolved, whether successfully or not. |
goog.net.EventType.SUCCESS |
Dispatched after the COMPLETE event fires if the request
completed successfully. |
goog.net.EventType.ERROR |
Dispatched after the COMPLETE event is dispatched if
the request did not complete successfully. |
goog.net.EventType.READY |
Dispatched
after the XhrIo instance has been reset
following the completion of the previous request. Indicates that
the XhrIo instance is ready for another
request. |
goog.net.EventType.TIMEOUT |
Dispatched if the request does not complete before the timeout
interval has elapsed (see Setting a Timeout
Interval). After the TIMEOUT event is dispatched, the
request is aborted, triggering the dispatch of a COMPLETE
event and then an ABORT event |
goog.net.EventType.ABORT |
Dispatched by the abort method
of XhrIo . Before dispatching
an ABORT event, the abort method:
|
In the quick example, for example, an event handler is attached to the XhrIo
instance xhr with the following code:
goog.events.listen(xhr, goog.net.EventType.COMPLETE, function(e) { var xhr = e.target; var obj = xhr.getResponseJson(); log('Received Json data object with title property of "' + obj['title'] + '"'); alert(obj['content']); });
Checking the Request's Status
XhrIo
provides several methods for checking the status of
a request and getting its results. You may find these methods useful
in your event listener functions:
Method | Returns |
---|---|
isActive() | true
if send() has been called on the XhrIo
instance and the request triggered by this call has not yet errored,
been aborted, or completed successfully. |
isComplete() | true if the
underlying XMLHttpRequest has
a readyState of 4. |
isSuccess() | true if the request
has completed without an error or timeout. |
getReadyState() | The readyState
of the underlying XMLHttpRequest . |
getStatus() | The HTTP status code sent by the server (200 for success, 404 if the URL wasn't found, etc.) if the server has started sending its response. If the server has not started responding, returns -1. |
getStatusText() | The status text sent by the server ("OK", "Not found", etc.) if the server has started sending its response. If the server has not started responding, returns an empty string. |
getLastUri | The last Uri that was requested. |
getLastErrorCode() |
A goog.net.ErrorCode value indicating
the outcome of the latest
request. goog.net.ErrorCode (defined
in closure/net/errorcode.js ) defines constants used to
record network error types, including the following types used
by XhrIo :
|
getLastError() | Text indicating the source of the error produced by the latest request, or an empty string if there was no error. |
getResponseHeader(key) | The value of the HTTP response header indicated by key. |
Retrieving Request Results
XhrIo
provides three methods for retrieving the results
of a request. If you need to get information back from the server,
then you will have to call one of these methods. These methods differ
from each other only with respect to the way in which the response
text is processed and returned: as raw text, as a JavaScript object
obtained by evaluating a JavaScript Object Notation (JSON) response,
or as Document object obtained by parsing an XML response.
Method | Returns |
---|---|
getResponseText() | The raw text of the response. The server's response can always be accessed with this method, no matter how it is encoded. |
getResponseJson() | Parses the response as JSON and returns the resulting object. The server's response must be JSON-encoded in order for this method to work. |
getResponseXml() | Returns
a Document object produced by parsing
the response text as XML. The server's response must have a content
type of "text/xml" in order for this to
work. The getResponseXml() method returns the value of
the responseXML property of the
underlying XMLHttpResponse object. |
Setting a Timeout Interval
The timeout interval is a property of the XhrIo
instance itself, and persists across requests. Set the timeout using
the goog.net.XhrIo.prototype.setTimeoutInterval()
method,
which takes a parameter indicating the number of milliseconds to wait
before aborting a request. XhrIo
interprets a timeout of
0 milliseconds as indicating no timeout at all. If you do not set a
timeout for the XhrIo
instance (or if you set a timeout
of 0), requests default to the browser's timeout, which is
usually 30 seconds.
Sending the Request
Once you have created an XhrIo
instance
and attached event listeners to handle the request results, initiate the
request by calling the instance's send()
method:
send(url, opt_method, opt_content, opt_headers)
- url
- indicates the uri to which you want to send the HTTP request.
- opt_method
- indicates the HTTP method of the request (usually either "POST" or "GET"). Defaults to "GET".
- opt_content
- contains the data to be posted for POST requests.
- opt_headers contains key-value pairs to be added to the HTTP request as headers. Either a plain JavaScript
Object
or
a goog.structs.Map
.
As discussed above, the send()
method does not take a
parameter indicating the timeout period to use for the request. By
default an XhrIo
instance has no timeout, but if you want
to set a timeout call setTimeoutInterval(interval)
before
calling send()
, where interval is the timeout
interval in milliseconds.