XMLHttpRequest

Events Model


After an XMLHttpRequest is created, it passes through a set of phases (states). To detect the current state of a request, the readyState property should be used. Each time the request gets a new state, a readystatechange event is dispatched. The event handler is attached to the request:

var xhr=new XMLHttpRequest(); // XHR readyState is 0, or UNSENT
xhr.onreadystatechange=xhrMonitor;
xhr.open("GET", "http://example.com/"); // asynchronous request
xhr.send(); // initiating the request
. . .
function xhrMonitor(event) { // asynchronous completion callback
 switch(event.target.readyState) {
  case 1:
  console.log("XMLHttpRequest state: OPENED.");
  break;
  case 2:
  console.log("XMLHttpRequest state: HEADERS_RECEIVED."); // header fields of the HTTP response have been received
  break;
  case 3:
  console.log("XMLHttpRequest state: LOADING."); // HTTP response entity body is being received
  break;
  case 4:
  console.log("XMLHttpRequest state: DONE."); // HTTP message exchange is over
  break;
  default:
  console.log("Request was not sent.");
  break;
 }
}

Reference to the XHR within the scope of the event handler is obtained as an EventTarget instance (event.target). Another way of reference is the use of this.

Progress Events

Detailed metrics of an XMLHttpRequest can be retrieved by implementing ProgressEvents handlers:

var xhr=new XMLHttpRequest();
xhr.onloadstart=progressMonitor;
. . .
xhr.open("GET", "very-large-guide.pdf");
xhr.send();
. . .
function progressMonitor(event) {
 console.log(event.type);
 console.log(event.total);
 console.log(event.loaded);
 console.log(event.timeStamp);
}

The following progress events are thrown when an XMLHttpRequest is sent:

loadstart: request starts; the value of the event's lengthComputable property is false; the number of bytes contained in the HTTP response entity is unknown (the total property is 0); no bytes are loaded yet (the loaded property is 0);

progress: the length of the response entity is computable now; the total number of bytes is known to the Web application; if the requested resource is large, the event is fired several times; each time a chunk of the response data is loaded; the number of received bytes is exposed as the value of the loaded property;

load: the HTTP message exchange is performed successfully; all bytes constituting the response are received; the values of the total and loaded properties are the same now;

error: the request has failed;

abort: the request is aborted; it can be done by calling the abort() method;

timeout: the timeout specified as a value of the XHR timeout property has run out before the request could complete;

loadend: the message exchange has completed, whether successfully or not.

Request States in Windows Scripts

Windows scripts for fetching Web resources from the command line support the monitoring of the ready state changes, too:

// cscript.exe xhr.js //NoLogo
var xhr=new ActiveXObject("Msxml2.XMLHTTP.6.0");
xhr.onreadystatechange=function() { // anonymous event handler
 WScript.Echo(xhr.readyState);
 switch(xhr.readyState) {
  case 0:
   WScript.Echo("State of the request: UNINITIALIZED. XMLHTTP object is created, but not initialized.");
  break;
  case 1:
   WScript.Echo("State of the request: LOADING. XMLHTTP object is created, but the send method has not been called.");
  break;
  case 2:
   WScript.Echo("State of the request: LOADED. The HTTP response headers are available.");
   WScript.Echo(xhr.getAllResponseHeaders());
  break;
  case 3:
   WScript.Echo("State of the request: INTERACTIVE.");
   WScript.Echo(xhr.status); // HTTP status code
  break;
  case 4:
   WScript.Echo("State of the request: COMPLETED. The HTTP response payload is available.");
   WScript.Echo(xhr.responseText);
  break;
  default:
   WScript.Echo("State of the request is unknown.");
  break;
 }
}
xhr.Open("GET", "http://example.com/", true);
xhr.Send();