XMLHttpRequest (XHR) objects are used to interact with servers. You can retrieve data from a URL without having to do a full page refresh. This enables a Web page to update just part of a page without disrupting what the user is doing. XMLHttpRequest is used heavily in AJAX programming.
Despite its name, XMLHttpRequest can be used to retrieve any type of data, not just XML.
If your communication needs to involve receiving event data or message data from a server, consider using server-sent events through the EventSource interface. For full-duplex communication, WebSockets may be a better choice.
XMLHttpRequest.response - Read only # Returns an ArrayBuffer, Blob, Document, JavaScript object, or a DOMString, depending on the value of XMLHttpRequest.responseType, that contains the response entity body.
XMLHttpRequest.responseText - Read only # Returns a DOMString that contains the response to the request as text, or null if the request was unsuccessful or has not yet been sent.
XMLHttpRequest.responseType # Is an enumerated value that defines the response type. # Possible values are the empty string (default), "arraybuffer", "blob", "document", "json", and "text". XMLHttpRequest.responseURL - Read only # Returns the serialized URL of the response or the empty string if the URL is null.
XMLHttpRequest.responseXML - Read only # Returns a Document containing the response to the request, or null if the request was unsuccessful, has not yet been sent, or cannot be parsed as XML or HTML. Not available in workers.
XMLHttpRequest.status - Read only # Returns an unsigned short with the status of the response of the request.
XMLHttpRequest.statusText - Read only # Returns a DOMString containing the response string returned by the HTTP server. Unlike XMLHttpRequest.status, this includes the entire text of the response message ("200 OK", for example).
XMLHttpRequest.timeout # Is an unsigned long representing the number of milliseconds a request can take before automatically being terminated.
XMLHttpRequestEventTarget.ontimeout # Is an EventHandler that is called whenever the request times out.
XMLHttpRequest.upload - Read only # Is an XMLHttpRequestUpload, representing the upload process.
XMLHttpRequest.withCredentials # Is a Boolean that indicates whether or not cross-site Access-Control requests should be made using credentials such as cookies or authorization headers.
Do not use synchronous requests outside Web Workers.
Analyzing and manipulating the responseXML property
If you use XMLHttpRequest to get the content of a remote XML document, the responseXML property will be a DOM object containing a parsed XML document. This could prove difficult to manipulate and analyze. There are four primary ways of analyzing this XML document:
Using XMLSerializer to serialize DOM trees to strings or to files.
RegExp can be used if you always know the content of the XML document beforehand. You might want to remove line breaks, if you use RegExp to scan with regard to line breaks. However, this method is a “last resort” since if the XML code changes slightly, the method will likely fail.
Processing a responseText property containing an HTML document
If you use XMLHttpRequest to get the content of a remote HTML webpage, the responseText property is a string containing the raw HTML. This could prove difficult to manipulate and analyze. There are three primary ways to analyze and parse this raw HTML string:
Use the XMLHttpRequest.responseXML property as covered in the article HTML in XMLHttpRequest.
Inject the content into the body of a document fragment via fragment.body.innerHTML and traverse the DOM of the fragment.
RegExp can be used if you always know the content of the HTML responseText beforehand. You might want to remove line breaks, if you use RegExp to scan with regard to linebreaks. However, this method is a “last resort” since if the HTML code changes slightly, the method will likely fail.
Handling binary data
Although XMLHttpRequest is most commonly used to send and receive textual data, it can be used to send and receive binary content. There are several well tested methods for coercing the response of an XMLHttpRequest into sending binary data. These involve utilizing the overrideMimeType() method on the XMLHttpRequest object and is a workable solution.
1 2 3 4 5
var oReq = new XMLHttpRequest(); oReq.open("GET", url); // retrieve data unprocessed as a binary string oReq.overrideMimeType("text/plain; charset=x-user-defined"); /* ... */
However, more modern techniques are available, since the responseType attribute now supports a number of additional content types, which makes sending and receiving binary data much easier.
For example, consider this snippet, which uses the responseType of “arraybuffer“ to fetch the remote content into a ArrayBuffer object, which stores the raw binary data.
XMLHttpRequest provides the ability to listen to various events that can occur while the request is being processed. This includes periodic progress notifications, error notifications, and so forth.
Support for DOM progress event monitoring of XMLHttpRequest transfers follows the specification for progress events: these events implement the ProgressEvent interface. The actual events you can monitor to determine the state of an ongoing transfer are:
progress
The amount of data that has been retrieved has changed.
load
The transfer is complete; all data is now in the response
// progress on transfers from the server to the client (downloads) functionupdateProgress (oEvent) { if (oEvent.lengthComputable) { var percentComplete = oEvent.loaded / oEvent.total * 100; // ... } else { // Unable to compute progress information since the total size is unknown } }
functiontransferComplete(evt) { console.log("The transfer is complete."); }
functiontransferFailed(evt) { console.log("An error occurred while transferring the file."); }
functiontransferCanceled(evt) { console.log("The transfer has been canceled by the user."); }
functionloadEnd(e) { console.log("The transfer finished (although we don't know if it succeeded or not)."); }
Submitting forms and uploading files
Instances of XMLHttpRequest can be used to submit forms in two ways:
Using the FormData API is the simplest and fastest, but has the disadvantage that data collected can not be stringified. Using only AJAX is more complex, but typically more flexible and powerful.
Using nothing but XMLHttpRequest
Submitting forms without the FormData API does not require other APIs for most use cases. The only case where you need an additional API is if you want to upload one or more files, where you use the FileReader API.
A brief introduction to the submit methods
An html can be sent in four ways:
using the POST method and setting the enctype attribute to application/x-www-form-urlencoded (default);
using the GET method (in this case the enctype attribute will be ignored).
1 2
# a string like the following will be added to the URL ?foo=bar&baz=The%20first%20line.%0AThe%20second%20line.
Using FormData objects
The FormData constructor lets you compile a set of key/value pairs to send using XMLHttpRequest. Its primary use is in sending form data, but can also be used independently from a form in order to transmit user keyed data. The transmitted data is in the same format the form’s submit() method uses to send data, if the form’s encoding type were set to “multipart/form-data”. FormData objects can be utilized in a number of ways with an XMLHttpRequest. For examples, and explanations of how one can utilize FormData with XMLHttpRequests, see the Using FormData Objects page. For didactic purposes here is a *translation* of the previous example transformed to use the FormData API.
functiontransferComplete(evt) { console.log("The transfer is complete."); }
functiontransferFailed(evt) { console.log("An error occurred while transferring the file."); }
functiontransferCanceled(evt) { console.log("The transfer has been canceled by the user."); }
Get last modified date
1 2 3 4 5 6 7 8
functiongetHeaderTime () { console.log(this.getResponseHeader("Last-Modified")); /* A valid GMTString date or null */ }
var oReq = new XMLHttpRequest(); oReq.open("HEAD"/* use HEAD if you only need the headers! */, "yourpage.html"); oReq.onload = getHeaderTime; oReq.send();
functionifHasChanged(sURL, fCallback) { var oReq = new XMLHttpRequest(); oReq.open("HEAD"/* use HEAD - we only need the headers! */, sURL); oReq.callback = fCallback; oReq.filepath = sURL; oReq.onload = getHeaderTime; oReq.send(); }
/* Let's test the file "yourpage.html"... */ ifHasChanged("yourpage.html", function (nModif, nVisit) { console.log("The page '" + this.filepath + "' has been changed on " + (newDate(nModif)).toLocaleString() + "!"); });
Cross-site XMLHttpRequest
Modern browsers support cross-site requests by implementing the Cross-Origin Resource Sharing (CORS) standard. As long as the server is configured to allow requests from your web application’s origin, XMLHttpRequest will work. Otherwise, an INVALID_ACCESS_ERR exception is thrown.
Bypassing the cache
A cross-browser compatible approach to bypassing the cache is appending a timestamp to the URL, being sure to include a “?” or “&” as appropriate.
As the local cache is indexed by URL, this causes every request to be unique, thereby bypassing the cache.
You can automatically adjust URLs using the following code:
The recommended way to enable cross-site scripting is to use the Access-Control-Allow-Origin HTTP header in the response to the XMLHttpRequest.
HTML in XMLHttpRequest
To discourage the synchronous use of XMLHttpRequest, HTML support is not available in the synchronous mode. Also, HTML support is only available if the responseType property has been set to "document". This limitation avoids wasting time parsing HTML uselessly when legacy code uses XMLHttpRequest in the default mode to retrieve responseText for text/html resources. Also, this limitation avoids problems with legacy code that assumes that responseXML is null for HTTP error pages (which often have a text/html response body).
1 2 3 4 5 6 7
var xhr = new XMLHttpRequest(); xhr.onload = function() { console.log(this.responseXML.title); } xhr.open("GET", "file.html", true); xhr.responseType = "document"; xhr.send();
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# Handling HTML on older browsers # Note: This solution is very expensive for the interpreter. Use it only when it is really necessary.