Categories:

JavaScript Kit > JavaScript Reference > Here

Ajax (XMLHttpRequest object)

Created: July 22nd, 2008

Ajax is a popular term used to describe asynchronous (versus synchronous) requests made from the client to the server. In JavaScript, Ajax requests are handled using the XMLHttpRequest object, which lets you open a connection, send the request, then handle the data returned by the server seamlessly in the background.

Related Tutorials

XMLHttpRequest Constructor

All Ajax requests in JavaScript begin by making a call to the XMLHttpRequest constructor function:

new XMLHttpRequest() //IE7, Firefox, Safari etc

new ActiveXObject("Msxml2.XMLHTTP") //newer versions of IE5+
new ActiveXObject("Microsoft.XMLHTTP") //older versions of IE5+
new XDomainRequest() //IE8+ only. A more "secure", versatile alternative to IE7's XMLHttpRequest() object.

In IE6 and below, the XMLHttpRequest() is not supported, but instead relies on the proprietary ActiveXObject for Ajax requests. This makes it necessary to roll your own cross browser HTTP Request constructor function to equalize the differences. Here is one such function you can use:

function ajaxRequest(){
 var activexmodes=["Msxml2.XMLHTTP", "Microsoft.XMLHTTP"] //activeX versions to check for in IE
 if (window.ActiveXObject){ //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken)
  for (var i=0; i<activexmodes.length; i++){
   try{
    return new ActiveXObject(activexmodes[i])
   }
   catch(e){
    //suppress error
   }
  }
 }
 else if (window.XMLHttpRequest) // if Mozilla, Safari etc
  return new XMLHttpRequest()
 else
  return false
}

//Usage:
new ajaxRequest()

Once equalized, the returned HTTP request instance shares the same properties and methods across browsers, thankfully.

Note: Any examples below use the custom HTTP request function above as their foundation.

Properties

Properties Description
readyState The "readyState" property keeps track of the current stage of the request by returning an integer:
  • 0: uninitialized
  • 1: loading
  • 2: loaded
  • 3: interactive
  • 4: complete

During each stage of the request, "onreadystatechange" fires to allow you to react to it.

responseText Returns the response data as a string.
responseXML Returns the response data- assumed to be a valid XML document- as a XML object that can be easily parsed using standard DOM methods. In order for the browser to correctly return an XML object using responseXML, you must ensure the following:
  1. Your XML document is well formed. responseXML will always return null if not.
  2. In Firefox, call request.overrideMimeType('text/xml') at the start of your Ajax request (upon instantiation) to explicitly tell the browser that the returned data will have a content type of "text/xml".
  3. IE doesn't support the client side overrideMimeType() method, so you must ensure that your server returns the proper "text/xml" content header type for the XML file that is being returned. If your XML file is named with an extension of ".xml", most servers by default send out the proper "text/xml" headers, though if it is not, you'll want to modify your server settings to do so. See "XML documents and the Content-type pitfall in IE" for more info.

If any one of the above conditions are not met, the data returned will be as plain text, not an XML object as expected. Here's a simple example of returning the first ELEMENT's node value within the XML file "test.xml" using Ajax:

var mygetrequest=new ajaxRequest()
if (mygetrequest.overrideMimeType)
 mygetrequest.overrideMimeType('text/xml')

mygetrequest.onreadystatechange=function(){
 if (mygetrequest.readyState==4){
  if (mygetrequest.status==200){
   var xmldata=mygetrequest.responseXML //retrieve result as an XML object
   var animals=xmldata.getElementsByTagName("theanimal")
   alert(animals[0].firstChild.nodeValue) //alerts "The dog is a domesticated subspecies..."

  }
  else{
   alert("An error has occured making the request")
  }
 }
}

mygetrequest.open("GET", "test.xml", true)
mygetrequest.send(null)

status Returns the status code of the request (integer), for example, 404 for a failed request, 200 for a successful one etc. When running your Ajax script online, to test for a fully complete and successful Ajax request, look for a readyState value of 4 plus a status code of 200:

var myrequest=new ajaxRequest()
myrequest.onreadystatechange=function(){
 if (myrequest.readyState==4){ //if request has completed
  if (myrequest.status==200){ //if request was successful (versus "page not found" etc)
   //do something with returned data
  }
 }
}

If you're running an Ajax request offline locally on your PC, a value of 0 is returned by status in most browsers regardless of the actual request status, even if it was successful. To run and test Ajax requests locally, it should overlook the status code being 200, and merely rely on a readyState value of 4. The following example takes into account the request possibly being run offline and to enable it:

var myrequest=new ajaxRequest()
myrequest.onreadystatechange=function(){
 if (myrequest.readyState==4){ //if request has completed
  if (myrequest.status==200 || window.location.href.indexOf("http")==-1){ //if request was successful (versus "page not found" etc) or if run offline (rely on readyState of 4 alone then)
   //do something with returned data
  }
 }
}

statusText The "natural language" version of the "status" property above, "statusText" returns the status of the request by name rather than by an integer.  Here are some "status" codes and their corresponding "statusText" values returned:
  • 200: "Ok"
  • 301: "Moved Permanently"
  • 304: "Not Modified" (page hasn't been modified)
  • 404: "Not Found"
  • 403: "Forbidden"
  • 401: "Unauthorized" (wrong password)
contentType

IE8 only. Supports this property if using the new XDomainRequest() object to create the Ajax request.

Allows you to explicitly set/get the contentType of the request, similar to Mozilla's overrideMimeType() method. See new XDomainRequest() on MSDN for more info.

var ie8ajaxrequest=new XDomainRequest()
ie8ajaxrequest.contentType="text/xml"

timeout

IE8 only. Supports this property if using the new XDomainRequest() object to create the Ajax request.

Maximum time allowed for the request to complete before the browser aborts the attempt. Fires "ontimeout" when that occurs. See new XDomainRequest() on MSDN for more info.

var ie8ajaxrequest=new XDomainRequest()
ie8ajaxrequest.timeout=2000
ie8ajaxrequest.ontimeout=function(){
 alert("Request has timed out. Please try again.")
}

Event handler

Properties Description
onreadystatechange Fires whenever the readyState property changes, allowing you to react to different stages of an asynchronous Ajax request. In some browsers such as Firefox, onreadystatechange fires multiple times while readyState is 3, letting you react as the data is downloading, such as to create a progress bar. IE (as of IE7) only fires onreadystatechange once during readyState of 3.

If your request is synchronous (as specified when calling ajaxrequest.open()), this event handler should not be defined, as the browser will still invoke it once even though there are no state changes.

onerror

Mozilla only. IE8 supports this via the new XDomainRequest() object.

Event handler that fires when there is an error with the request. A simpler alternative to using the onreadystatechange event handler plus probing the status property to react to an error.
onload

Mozilla only. IE8 upports this via the new XDomainRequest() object.

Event handler that fires when the request has completely downloaded. A simpler alternative to using the onreadystatechange event handler plus probing the readyState property to detect when the request is complete.
onprogress

Mozilla only. IE8 supports this via the new XDomainRequest() object.

Fires multiple times as (large) data is being returned. This lets you display real time progress information to visitors as the data is being downloaded. In Mozilla, the onprogress event handler is inexplicitly passed an event object that contains the following two properties:
  • eventobj.position: The current number of bytes received
  • eventobj.totalSize: The total size of the data being retrieved.

For example:

var myrequest=new ajaxRequest()
myrequest.onprogress=function(e){
 var currentpercent: (e.position/e.totalSize)*100
 window.status="Downloading data. Percentage complete: "+currentpercent+"%"
}

ontimeout

IE8 only. Supports this property if using the new XDomainRequest() object to create the Ajax request.

 

Fires when an Ajax request has timed out per the "timeout" setting value.

var ie8ajaxrequest=new XDomainRequest()
ie8ajaxrequest.timeout=2000
ie8ajaxrequest.ontimeout=function(){
 alert("Request has timed out. Please try again.")
}

Methods

Note: "[]" surrounding a parameter below means the parameter is optional.

Methods Description
abort() Aborts the current Ajax request that's in session. readyState property is reset to 0. Since the XMLHttpRequest() object doesn't have a built-in timer you can use to specify when abort() should be called, you need to build your own. The following aborts an Ajax connection if it has yet to be completed after 5 seconds:

var myrequest=new ajaxRequest()
myrequest._timeout=setTimeout(function(){
 myrequest.abort()
 },
 5000
) //end setTimeout

open(method, url, [[async], [username], [password]) Sets the URL and type of the Ajax request before it is actually sent. The last two optional parameters allow you to pass in a username/password for authenticated requests:
  1. Method: Enter "GET" for GET requests, "POST" for POST requests. Other possible values include "HEAD" or "PUT".
  2. url: The relative or full URL to the Ajax request. All modern browsers restrict this url to the same domain as the page making the request. For cross domain Ajax requests, a "web proxy" needs to be used to first bring the data from the remote host onto the current, such as via PHP's file_get_contents() method or Curl before opening a request to the local copy of the data.
  3. async: Optional Boolean parameter that specifies whether the request should be asynchronous (default) or synchronous (true=async, false=sync). In the later, the request stalls the loading of the rest of the page until the request is completed.
  4. username: Optional parameter for specifying the username of an authenticated request.
  5. password: Optional parameter for specifying the password of an authenticated request.

For "GET" requests, pass any parameters that should be sent along with the request by adding it to the url followed by a question mark (?), for example:

var myrequest=new ajaxRequest()
myrequest.open("GET", "result.php?id=george&age=30", true)

Be sure to use encodeURIComponent() on any parameter values that may contain special characters such as spaces or "=" etc. For "POST" requests, parameters are entered inside request.send() instead.

As mentioned, by default the browser restricts the domain portion of the URL entered into request.open() to only those that match that of the calling page. If you're using an absolute URL, the URL's hostname must match exactly the calling page's. This means even "http://mysite.com" and "http://www.mysite.com" are treated as different (non matching) hostnames. To ensure an absolute URL request's hostname matches the calling page's, you can have JavaScript dynamically construct that portion of the URL:

var myrequest=new ajaxRequest()
var myhostname="http://"+window.location.hostname
myrequest.open("GET", myhostname+"/mydir/response.php", true)

send(data) Sends the request to the server with a "data" parameter specifying the body of the request. For "GET" requests, this parameter should be a value of null, while for "POST" requests, the parameters of the request. This method typically should always be called last.

Ajax GET request:

var myrequest=new ajaxRequest()
myrequest.open("GET", "result.php?id=george&age=30", true)
myrequest.send(null) //send GET request

Ajax POST request:

var myrequest=new ajaxRequest()
var parameters="id=george&age=30"
myrequest.open("GET", "result.php", true)
myrequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
myrequest.send(parameters) //send POST request

getResponseHeader(header) Gets the value of the specified response header of an Ajax request, such as the value for "Content-Type". The parameter value is case insensitive. It is up to your server to return the anticipated value for a header. You should only call getResponseHeader() after the request is complete based on its readyState property (otherwise it returns a blank string).

Here's an example that probes the content type of the request to decide what data to return:

var myrequest=new ajaxRequest()
myrequest.onreadystatechange=function(){
 if (myrequest.readyState==4){ //if request has completed
  if (myrequest.status==200){ //if request was successful (versus "page not found" etc)
   var contentType=myrequest.getResponseHeader("Content-Type")
   if (contentType=="text/xml") //XML Data (make sure server sends out correct header)?
    return myrequest.responseXML
   else if (contentType=="text/json") //JSON Data (make sure server sends out correct header)?
    return eval(myrequest.responseText) //(beware of cross domain security issues)
   else // Text Data
    return myrequest.responseText
  }
 }
}

getAllResponseHeaders() Gets the values of all response headers from the Ajax request as one string. You should only call getAllResponseHeaders() after the request is complete based on its readyState property (otherwise it returns a blank string).
setRequestHeader(header, value) Lets you set a header that gets sent along with the request to the server (not to be confused with the header that gets returned by the server). This method MUST be called in between request.open() and request.send().

For Ajax "POST" requests, always send a "Content-type" header of "application/x-www-form-urlencoded".

var myrequest=new ajaxRequest()
"
"
myrequest.open("POST", "submit.php", true)
myrequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
myrequest.send("id=" + encodeURI(somevalue))


Reference List

Partners
Right column

CopyRight 1998-2014 JavaScript Kit. NO PART may be reproduced without author's permission.