最简单的方法获取跨浏览器XmlHttpRequest

42

如何在所有浏览器中获取XmlHttpRequest对象的最简单和最安全的方法?不使用任何额外的库。您是否经常使用代码片段?

P.S. 我知道互联网上有大量的示例,但这正是我提问的原因:有太多不同的示例,我只想要一些简单且经过验证的代码。

不考虑使用jQuery等其他库。 为什么jquery内存泄漏如此严重?


1
我知道你说“不使用外部库”,但答案仍然是“使用jQuery”。它压缩后不到25k。 - cletus
1
另一个很棒的库是原型。但是,你能解释一下为什么不想使用库吗?它们可以让你的生活变得更轻松。 - The Code Pimp
25
jQuery泄漏内存,仅为了进行一个ajax请求而使用库是严重的过度设计。 - Egor Pavlikhin
29
当问题中明确说明“不使用任何额外的库”时,请停止提出使用库的建议。显然,您可以使用许多不同的库来完成这项任务,但这并不是我的问题要点。另外,正如我所说的,jQuery的ajax对象会泄露内存,这对我非常重要。 - Egor Pavlikhin
5
请检查我提供的链接。不要轻易称呼别人为愚蠢。 - Egor Pavlikhin
显示剩余6条评论
4个回答

67

虽然我建议使用完整的库来使使用更加容易,但在现代浏览器中进行 AJAX 请求可以非常简单:

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();

以下代码片段是基于quirksmode.org的一个更高级的片段,甚至支持比 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;
}

1
@Rob,http://code.google.com/p/xmlhttprequest/ 是一个专门用来解决浏览器泄漏问题的跨浏览器XMLHttpRequest。然而,我在上面的代码中也没有发现任何泄漏问题。 - Egor Pavlikhin
1
req.setRequestHeader('User-Agent','XMLHTTP/1.0'); 这行代码是否必要?最新版的 Chrome 会忽略它。 - ikari
1
@ikari:我预计这是旧版Internet Explorer的要求,它是否仍然与您有关取决于您的用户 :) - Wolph
1
@BorisD.Teoharov:整个答案已经过时,已经超过7年了。我建议使用一个简单的new XMLHttpRequest(),任何不支持它的浏览器都不适合现代互联网。 - Wolph
1
@BorisD.Teoharov 我稍微更新了一下示例,希望能有所帮助 :) - Wolph
显示剩余5条评论

13

如所要求,简单易行且经过验证

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;
}

将其折叠成一行,我们得到:

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;
}

2
根据IE Dev Center的说法,我引用一下:"为了支持早于IE7版本的IE,您可以使用:" return new ActiveXObject("MSXML2.XMLHTTP.3.0") - andreszs
@Andrew,是的,链接在这里:https://msdn.microsoft.com/en-us/library/ms535874(v=vs.85).aspx#code-snippet-4。旧浏览器真的很头疼,尽管现在对于个人项目,我最可能只是简单地使用“new XMLHttpRequest();”。 - Pacerier

4

我不太确定你的问题,但如果你想要一个能够在所有浏览器中使用的XMLHTTP实例的函数,我们已经在我们的本地ajax库中使用了多年,而且在任何浏览器中都没有出现过问题。

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
}

1
一个更简单的方法:

检测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;
}

区分XMLhttp和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
}

完整示例可以在这里找到


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接