jQuery ajax() option - xhr

For this function, you want to return an appropriate XHR object for your browser. The default behavior is to use XMLHTTPRequest or the IE equivalent. Here's the default behavior:

jQuery.ajaxSettings.xhr = window.ActiveXObject ?
/* Microsoft failed to properly
 * implement the XMLHttpRequest in IE7 (can't request local files),
 * so we use the ActiveXObject when it is available
 * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
 * we need a fallback.
 */
function() {
    return !this.isLocal && createStandardXHR() || createActiveXHR();
} :
// For all other browsers, use the standard XMLHttpRequest object
createStandardXHR;

Those two create methods createStandardXHR and createActiveXHR essentially call the basic XHR creation methods we've all known and loved for years. Here's createStandardXHR:

function createStandardXHR() {
try {
    return new window.XMLHttpRequest();
} catch( e ) {}
}

So, if you wanted to override this, you can simply pass in your own function that returns a new XMLHttpRequest() object.

Why would you want to do this? Let's say you need to make a cross domain HTTP request and are using an IFRAME shim to make it work using document.domain to work within the same origin rules. This is a good way to make your javascript load the XHR object from the correct frame based on what domain you want to talk to.

Twitter.com uses this technique.

JavaScript runs on http://twitter.com/ but the data is at http://api.twitter.com. They create an IFRAME pointing at api.twitter.com that simply sets document.domain to "twitter.com". They set document.domain to "twitter.com" in the main page, too.

Then, their JS, when making HTTP requests, just creates it from the IFRAME instead of the main page. Gets them through the same-origin policy.

You can do this with the xhr option to $.ajax(). Here's a snippet (imagine this code running on a page at http://myapp.com):

$.ajax({url: "http://api.myapp.com", xhr: function(){
  return new ($('#my_api_iframe')[0].contentWindow.XMLHttpRequest)();
}, success: function(html) {
    // format and output result
   }
});

That will work as long as both the main page and the iframe set their document.domain to the same value. (This is a hackish example: it won't work in some IE versions because I cheated and only used the standard XMLHttpRequest object - you'll need to fix.)

Hope that helps.

(edited to add: this is a technique necessary for older browsers - CORS support in most modern browsers would make this unnecessary)

Sujal


In fact, someone does know.

The xhr option allows you to define your own callback for creating the XMLHttpRequest object that will be used behind the scenes in the ajax() call. In pretty much every single case, you shouldn't need to specify this option.


Another late answer, but the code below is a great example of what you can do when you override the xhr option. This is taken from Ben Nolan's blog It allows you to track the progress of an xhr get. I used this to create a progress bar when loading a large json data set, exactly the same thing he created it for. It helped me a ton.

interval = null

$.ajax {
  url : "endpoint.json"

  dataType : 'json'

  xhr : () =>
    xhr = jQuery.ajaxSettings.xhr()

    interval = setInterval( =>
      if xhr.readyState > 2
        total = parseInt(xhr.getResponseHeader('Content-length'))
        completed = parseInt(xhr.responseText.length)
        percentage = (100.0 / total * completed).toFixed(2)

        console.log "Completed #{percentage}%"
    , 50)

    xhr

  complete: ->
    clearInterval(interval)

  success : (data) =>
    alert(data)
}

Tags:

Jquery