IE + XMLHttpRequest problem and solution

I just found, yet another IE + JavaScript problem
First let me declare myself as NOT-IE-HATER. I do not hate or love any browser.
I just do not like to suffer consequences (daily) of bad software design decisions, or indecisions. So, this is one of them that (has not) made my day today.
It seems, bad decision was made here : http://blogs.msdn.com/ie/archive/2006/01/23/516393.aspx
Explanation. Any IE javascript does this OK, (as per ES3 spec):

o = {}
typeof o.f === undefined 
Object.prototype.toString.call(o.f) === "[object Object]"

But … IE has ActiveX controls. And there is one which we have to use very often. XMLHttpRequest. Ok, so what is the problem, actually ?
This problem is very subtle, and as a such it can generate very subtle bugs.
The issue is that in IE (vs others) you can not call the XMLHttpRequest(). In IE it is of a type “object”.

// the source of trouble
typeof XMLHttpRequest === "object" // only in IE ?
// it can not be called
XMLHttpRequest()
/* TypeError, Number : 5
Description : Invalid procedure call or argument */
// it must be new-ed,  it is "scriptable and native" but still it is an ActiveX (COM) object
new XMLHttpRequest()
// OK

And (lo and behold) this is a source of a lot of trouble and workarounds.
Especially in libraries and any( trying to be) generic javascript.

typeof XMLHttpRequest.toString
/* unknown */
Object.prototype.toString.call(XMLHttpRequest.toString)
/* TypeError , Number : 438
Description : Object doesn't support this property or method */

Has, someone forgot to handle “unknown” in Object.prototype.toString.call() ?
Why having “unknown” at all? Why not treat it as undefined, and no confusion:

// how IE+javascript should behave to be more "ES3"
typeof XMLHttpRequest.toString === undefined 
Object.prototype.toString.call(XMLHttpRequest.toString) == "[object Object]"

Even better why not just making XMLHttpRequest a native global function ? As everybody else, as far as I know? And after all the same as IE’s own window.ActiveXObject() :

// ultimate solution for IE
typeof window.XMLHttpRequest === "function"

Since the proper cross-browser way (also for IE since IE7) is this :

// a proper cross-browser way
var xhr = new XMLHttpRequest() ;

Changing (in IE) XMLHttpRequest from object to function will brake no legacy code.
With that change the following will behave in IE as in any other ES3 compatible browser:

typeof XMLHttpRequest === "function"
Object.prototype.toString.call(XMLHttpRequest) === "[object Function]" ;
typeof XMLHttpRequest.toString === undefined ;
// and so on ...

This change, if implemented will improve the consistency of IE scripting and will cost almost nothing.

Tagged on: ,

3 thoughts on “IE + XMLHttpRequest problem and solution

  1. Dusan Post author

    Of course above does not brake IE versions bellow 7. They have no global object or function called : XMLHttpRequest . Same applies for any other legacy browser “out there” and still in use.
    (WikiPedia article)

  2. kunal

    browser do have cashing enable so it displays the old output if it gets same query string parameter. so solution for the problem is to try to send request with different query string parameter value each time….. below is the sample example

    function FetchDGContents(SortField,SortType,hlp)
    {
    	//var selecteditem = document.Form1.ddlcity.value;
    	//Starts displaying the Process Image table
    	//imgtbl.style.visibility = 'visible';
    
        var vReqid=Math.random() * 1000;
        var requestUrl = "/WebPF/HELP/Help.aspx?req="+(vReqid)+"&searchstr="+SortField+"&hlp="+SortType+"&fldname="+hlp;
        /// 
    	CreateXmlReq();
    	
        if(XmlReq)
    	{
            XmlReq.abort();
    	    XmlReq.open("GET", requestUrl,  false);
    	    XmlReq.send(null);
    	    XmlReq.onreadystatechange = HandleResponse;
    	}
    }
    
  3. Dusan Post author

    @kunal
    Er … sorry is Your comment for this or some other article ?
    Beyond that, the world is using jQuery, last few years or so, for these kind of issues :)

Leave a Reply