Shorter XHR Abstraction

Ajaxian posted about Nicolas Faugout's approach to abstract the XMLHttpRequest object.

if (!XMLHttpRequest) {
  function XMLHttpRequest() {
    return new ActiveXObject('Microsoft.XMLHTTP');
  }
}

The problem, as pointed out in the comments of that article is that Internet Explorer declares the function before it runs the code. In Firefox (and possibly others), it doesn't. Therefore, it seems like this works. The problem is that IE7 now has a native XHR object. This code doesn't take that into account and would overwrite the native object and try to use the ActiveX object. If users have ActiveX objects disabled in IE7, they'll be out of luck and won't be able to use your fancy Ajax.

Is there another way? Leave it to conditional comments to come to the rescue:

/*@cc_on
@if (@_jscript_version >= 5 && @_jscript_version < 5.7)
  function XMLHttpRequest() {
    try{
      return new ActiveXObject(Msxml2.XMLHTTP');
      }catch(e){}
  }
@end
@*/

The conditional comments get turned on and ensure that no other browser but Internet Explorer will recognize and run this code. Furthermore, it checks the version of JScript to make sure it's within a specific range. Jscript 5.7 is the version that shipped with IE7; which, of course, is the version with the native XHR object.

I even threw in the try/catch block so that it doesn't throw an automation error in IE6 if the object doesn't exist.

In doing some research to see how other people may have attacked this problem, you can check out the following:

So, can you improve on this? Is it possible to make it shorter?

Published April 18, 2007
Categorized as JavaScript
Short URL: https://snook.ca/s/796

Conversation

7 Comments · RSS feed
Jonathan Snook said on April 18, 2007

Elad just left a comment on the Ajaxian article:

if (!window.XMLHttpRequest) {
  window.XMLHttpRequest=function () {
    return new ActiveXObject('Microsoft.XMLHTTP');
  }
}

It should probably still have the try/catch block but otherwise. This should work.

Ash Searle said on April 18, 2007

The Ajaxian thing has trackbacks to 3 new blog entries with titles of "blah blah XHR abstraction blah blah blah"

Perhaps, to emphasize the fact that it's an abstraction, and because everyone's using the term XHR anyway, you could go with the compact:

XHR = XMLHttpRequest || function() {
    return new ActiveXObject('Microsoft.XMLHTTP');
}

Then, when programmers use new XHR() it's obvious they're not necessarily getting a native implementation of XMLHttpRequest.

It's just a thought.

Jonathan Snook said on April 18, 2007

@Ash: the question is, should any need to adjust implementation -- such as enabling addEventListener functionality in IE -- warrant an abstraction of the whole process? Certainly that's what most libraries do: build an API on top of an API.

Dustin Diaz said on April 19, 2007

Needless to say, it sounds like the true problem isn't the abstraction, but a better use of branching. Branching shouldn't happen upon every request, but rather once at runtime of the page.

Tobie Langel said on April 28, 2007

Although I agree with you in general Dustin, you'll have to admit that the bottle-neck in an Ajax request certainly isn't the branching.

steve said on August 13, 2007

MS is now shipping the 5.7 scripting engine as a standalone install.
http://blogs.msdn.com/jscript/archive/2007/08/12/windows-script-5-7-released-for-windows-2000-windows-xp-and-windows-2003-server.aspx
I suspect this means that someone running IE6 might now also have JS 5.7. In this case your sniff code won't define the needed ctor.

eugene said on August 14, 2007

objREQ = window.ActiveXObject == false ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP") ;

Sorry, comments are closed for this post. If you have any further questions or comments, feel free to send them to me directly.