42

What is the easiest and safest way to retrieve XmlHttpRequest object that works across all browsers? Without any extra libraries. Is there a code snippet you use often?

P.S. I know there are tons of examples on the net, but this is precisely the reason I am asking: there are too many different examples, and I just want something simple and proven to work.

jQuery and other libraries is NOT an option. Why does jquery leak memory so badly?

Community
  • 1
  • 1
Egor Pavlikhin
  • 17,503
  • 16
  • 61
  • 99
  • 1
    I know you say "without using external libraries" but the answer is *still* "use jQuery". It's under 25k gzipped. – cletus Mar 31 '10 at 23:47
  • jQuery is used because it is simple and easy –  Mar 31 '10 at 23:47
  • 1
    Another great library is prototype. However, could you explain why you don't want to use a library? They could make your life much easier.. – The Code Pimp Mar 31 '10 at 23:49
  • 25
    jQuery leaks memory and using a library just to make one ajax request is a serious overkill. – Egor Pavlikhin Mar 31 '10 at 23:50
  • I think a JS library can be considered "standard overhead"; besides 25k is nothing. You'll probably find many more uses for jQuery once you include it. – Matti Virkkunen Mar 31 '10 at 23:53
  • 1
    25k is nothing in terms of downloading, in terms of parsing and executing the javascript it can make a noticable difference in some browsers. But I agree that it is nearly always the least of your problems. – Wolph Mar 31 '10 at 23:55
  • 29
    Please stop suggesting libraries when the question states "Without any extra libraries". It is pretty obvious that you can do this with tons of different libraties, that is not the point of my question. And as I said jQuery's ajax object leaks memory, which is crucial for me. – Egor Pavlikhin Mar 31 '10 at 23:56
  • 5
    Check the link I have provided. And don't call people stupid on the whim. – Egor Pavlikhin Apr 01 '10 at 00:01
  • 1
    Retrieving a "XmlHttpRequest object" works "across all browsers". – Chris Lercher Apr 01 '10 at 00:08
  • @M28, jQuery isn't the only solution, just like regular expressions aren't. – strager Apr 01 '10 at 00:09
  • @HeavyWave, Try an older or newer version of jQuery to see if they fix the problem you are having. – strager Apr 01 '10 at 00:11

4 Answers4

67

While I would recommend using a full library to make usage easier, making AJAX requests can be fairly simple in modern browsers:

var req = new XMLHttpRequest();
req.onreadystatechange = function(){
    if(this.readyState == 4){
        alert('Status code: ' + this.status);
        // The response content is in this.responseText
    }
}
req.open('GET', '/some-url', true);
req.send();

The following snippet is a more advanced snippet based on a snippet from quirksmode.org and even supports very old browsers (older than Internet Explorer 7):

function sendRequest(url,callback,postData) {
    var req = createXMLHTTPObject();
    if (!req) return;
    var method = (postData) ? "POST" : "GET";
    req.open(method,url,true);
    // Setting the user agent is not allowed in most modern browsers It was
    // a requirement for some Internet Explorer versions a long time ago.
    // There is no need for this header if you use Internet Explorer 7 or
    // above (or any other browser)
    // req.setRequestHeader('User-Agent','XMLHTTP/1.0');
    if (postData)
        req.setRequestHeader('Content-type','application/x-www-form-urlencoded');
    req.onreadystatechange = function () {
        if (req.readyState != 4) return;
        if (req.status != 200 && req.status != 304) {
//          alert('HTTP error ' + req.status);
            return;
        }
        callback(req);
    }
    if (req.readyState == 4) return;
    req.send(postData);
}

var XMLHttpFactories = [
    function () {return new XMLHttpRequest()},
    function () {return new ActiveXObject("Msxml3.XMLHTTP")},
    function () {return new ActiveXObject("Msxml2.XMLHTTP.6.0")},
    function () {return new ActiveXObject("Msxml2.XMLHTTP.3.0")},
    function () {return new ActiveXObject("Msxml2.XMLHTTP")},
    function () {return new ActiveXObject("Microsoft.XMLHTTP")}
];

function createXMLHTTPObject() {
    var xmlhttp = false;
    for (var i=0;i<XMLHttpFactories.length;i++) {
        try {
            xmlhttp = XMLHttpFactories[i]();
        }
        catch (e) {
            continue;
        }
        break;
    }
    return xmlhttp;
}
Wolph
  • 78,177
  • 11
  • 137
  • 148
  • We are already using jQuery, however it leaks memory, which is crucial in our case. Thanks for the snippet, I'll try it out. – Egor Pavlikhin Mar 31 '10 at 23:58
  • Which browser uses Msxml3 ? I haven't seen it before. – Egor Pavlikhin Apr 01 '10 at 00:18
  • Any system that doesn't have Msxml6 available (which Microsoft.XMLHTTP will call). I know that atleast Windows 2000 SP4 has Msxml3 available :) – Wolph Apr 01 '10 at 00:53
  • I'm not familiar with jQuery (as I use ExtJS), but it might be worth (if you do use the functions above), formulating the method names/API so it's similar to whatever javascript library you intend to eventually use, if any, to make migrating across once the memory leak has gone away easier. – Rob Apr 01 '10 at 09:35
  • 1
    @Rob, http://code.google.com/p/xmlhttprequest/ cross-browser xmlhttprequest specifically made to fight leaks. However I couldn't find any leaks with the code above either. – Egor Pavlikhin Apr 01 '10 at 13:27
  • 1
    is `req.setRequestHeader('User-Agent','XMLHTTP/1.0');` actually necessary? Newest Chrome says it's gonna ignore this anyway. – ikari Mar 13 '14 at 08:28
  • 1
    @ikari: I expect it to be a requirement of older versions of Internet Explorer, whether it is still relevant to you depends on your users of course :) – Wolph Mar 15 '14 at 08:06
  • 1
    @BorisD.Teoharov: the entire answer is deprecated, it's over 7 years old. I would recommend using a plain `new XMLHttpRequest()`, any browser that doesn't support it is not fit for the modern internet anyhow. – Wolph Jun 17 '17 at 11:53
  • Thanks Wolph ! I didn't notice. I always have it in mind that IE might provide different APIs. Maybe the first time in years I needed to use plain JS for AJAX call. – Boris D. Teoharov Jun 18 '17 at 01:26
  • 1
    @BorisD.Teoharov I've updated the example a bit, that should help :) – Wolph Jun 20 '17 at 17:32
13

As requested, simple and proven to work:

function Xhr(){ /* returns cross-browser XMLHttpRequest, or null if unable */
    try {
        return new XMLHttpRequest();
    }catch(e){}
    try {
        return new ActiveXObject("Msxml3.XMLHTTP");
    }catch(e){}
    try {
        return new ActiveXObject("Msxml2.XMLHTTP.6.0");
    }catch(e){}
    try {
        return new ActiveXObject("Msxml2.XMLHTTP.3.0");
    }catch(e){}
    try {
        return new ActiveXObject("Msxml2.XMLHTTP");
    }catch(e){}
    try {
        return new ActiveXObject("Microsoft.XMLHTTP");
    }catch(e){}
    return null;
}

Collapsing it into a single line, we get:

function Xhr(){
    try{return new XMLHttpRequest();}catch(e){}try{return new ActiveXObject("Msxml3.XMLHTTP");}catch(e){}try{return new ActiveXObject("Msxml2.XMLHTTP.6.0");}catch(e){}try{return new ActiveXObject("Msxml2.XMLHTTP.3.0");}catch(e){}try{return new ActiveXObject("Msxml2.XMLHTTP");}catch(e){}try{return new ActiveXObject("Microsoft.XMLHTTP");}catch(e){}return null;
}
Pacerier
  • 86,231
  • 106
  • 366
  • 634
  • 2
    According to the IE Dev Center, and I quote, "To support IE versions older than IE7, you can use:" return new ActiveXObject("MSXML2.XMLHTTP.3.0") – andreszs Aug 15 '14 at 23:37
  • @Andrew, Yea, link is here: https://msdn.microsoft.com/en-us/library/ms535874(v=vs.85).aspx#code-snippet-4 . Old browsers are really headaches, though these days for personal projects I'd most likely simply do `new XMLHttpRequest();`. – Pacerier Nov 26 '15 at 04:58
4

not 100% certain of your question - but if you're asking for function to return a cross browser XMLHTTP instance - we have used this in our native ajax library for years - and never a problem in any browser

function getXMLHTTP() {
    var alerted;
    var xmlhttp;
    /*@cc_on @*/
    /*@if (@_jscript_version >= 5)
    // JScript gives us Conditional compilation, we can cope with old IE versions.
    try {
        xmlhttp=new ActiveXObject("Msxml2.XMLHTTP")
    } catch (e) {
    try {
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP")
    } catch (E) {
        alert("You must have Microsofts XML parsers available")
    }
    }
    @else
        alert("You must have JScript version 5 or above.")
        xmlhttp=false
        alerted=true
    @end @*/
    if (!xmlhttp && !alerted) {
        // Non ECMAScript Ed. 3 will error here (IE<5 ok), nothing I can
        // realistically do about it, blame the w3c or ECMA for not
        // having a working versioning capability in  <SCRIPT> or
        // ECMAScript.
        try {
            xmlhttp = new XMLHttpRequest();
        } catch (e) {
            alert("You need a browser which supports an XMLHttpRequest Object")
      }
    }
    return xmlhttp
}
Qix - MONICA WAS MISTREATED
  • 14,451
  • 16
  • 82
  • 145
plodder
  • 2,304
  • 18
  • 19
1

A simpler way:

Detect IE:

function detectIE() {
  var ua = window.navigator.userAgent,
   msie = ua.indexOf('MSIE '),
   trident = ua.indexOf('Trident/'),
   edge = ua.indexOf('Edge/');
   if (msie > 0) {return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);}
   if (trident > 0) {var rv = ua.indexOf('rv:');return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);}
   if (edge > 0) {return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);}
   return false;
}

Differentiate XMLhttp and XDomain:

var url = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%27pune%2Cmh%27)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithke"
if (window.XDomainRequest && detectIE()) {
    var xdr = new XDomainRequest();
    xdr.open("GET", url, false);
    xdr.onload = function () {
      var res = JSON.parse(xdr.responseText);
      if (res == null || typeof (res) == 'undefined')
      {
        res = JSON.parse(data.firstChild.textContent);
      }
      publishData(res);
  };
  xdr.send();
} else {
  var xmlhttp = new XMLHttpRequest();
  xmlhttp.onreadystatechange = function() {
  if (xmlhttp.readyState == 4) {
    if (xmlhttp.status == 200 || xmlhttp.status == 304) {
      publishData(JSON.parse(xmlhttp.responseText));
    } else {
      setTimeout(function(){ console.log("Request failed!") }, 0);
    }
  }
}
  xmlhttp.open("GET", url, true);
  xmlhttp.send();
}

function publishData(data){
  console.log(data); //Response
}

Full Example can be found here

Krunal
  • 725
  • 7
  • 15