检索跨浏览器 XmlHttpRequest 的最简单方法

Posted

技术标签:

【中文标题】检索跨浏览器 XmlHttpRequest 的最简单方法【英文标题】:Easiest way to retrieve cross-browser XmlHttpRequest 【发布时间】:2011-02-03 04:12:48 【问题描述】:

检索适用于所有浏览器的 XmlHttpRequest 对象的最简单和最安全的方法是什么?没有任何额外的库。有没有你经常使用的代码sn-p?

附:我知道网上有很多例子,但这正是我要问的原因:不同的例子太多了,我只想要一些简单且被证明有效的东西。

jQuery 和其他库不是一个选项。 Why does jquery leak memory so badly?

【问题讨论】:

我知道你说“不使用外部库”,但答案是仍然“使用 jQuery”。压缩后不到 25k。 另一个很棒的库是原型。但是,你能解释一下为什么你不想使用图书馆吗?他们可以让你的生活更轻松.. jQuery 会泄漏内存,使用库只是为了发出一个 ajax 请求是一种严重的过度杀伤力。 当问题显示“没有任何额外的库”时,请停止推荐库。很明显,您可以使用大量不同的库来做到这一点,这不是我问题的重点。正如我所说,jQuery 的 ajax 对象会泄漏内存,这对我来说至关重要。 检查我提供的链接。不要一时兴起就称人们为愚蠢。 【参考方案1】:

虽然我建议使用完整的库来简化使用,但在现代浏览器中发出 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();

以下 sn-p 是基于 quirksmode.org 的 sn-p 的更高级的 sn-p,甚至支持非常旧的浏览器(比 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;

【讨论】:

@Rob, code.google.com/p/xmlhttprequest 跨浏览器 xmlhttprequest 专门用于防止泄漏。但是我也找不到上面代码的任何泄漏。 req.setRequestHeader('User-Agent','XMLHTTP/1.0'); 真的有必要吗?最新的 Chrome 表示无论如何它都会忽略这一点。 @ikari:我希望它是旧版本 Internet Explorer 的要求,当然它是否仍然与您相关取决于您的用户 :) @BorisD.Teoharov:整个答案已被弃用,它已经超过 7 年了。我建议使用普通的new XMLHttpRequest(),任何不支持它的浏览器都不适合现代互联网。 @BorisD.Teoharov 我已经稍微更新了示例,这应该会有所帮助:)【参考方案2】:

不是 100% 确定您的问题 - 但如果您要求函数返回一个跨浏览器 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

【讨论】:

【参考方案3】:

根据要求,简单且行之有效

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()
    tryreturn new XMLHttpRequest();catch(e)tryreturn new ActiveXObject("Msxml3.XMLHTTP");catch(e)tryreturn new ActiveXObject("Msxml2.XMLHTTP.6.0");catch(e)tryreturn new ActiveXObject("Msxml2.XMLHTTP.3.0");catch(e)tryreturn new ActiveXObject("Msxml2.XMLHTTP");catch(e)tryreturn new ActiveXObject("Microsoft.XMLHTTP");catch(e)return null;

【讨论】:

根据IE开发中心,我引用,“要支持IE7之前的IE版本,你可以使用:” return new ActiveXObject("MSXML2.XMLHTTP.3.0") @Andrew,是的,链接在这里:msdn.microsoft.com/en-us/library/…。旧浏览器真的很让人头疼,尽管这些天对于个人项目我很可能只是简单地做new XMLHttpRequest();【参考方案4】:

更简单的方法:

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

完整的例子可以在here找到

【讨论】:

以上是关于检索跨浏览器 XmlHttpRequest 的最简单方法的主要内容,如果未能解决你的问题,请参考以下文章

ubuntu(linux)下谷歌浏览器跨域问题,XMLhttprequest跨域问题

浏览器原理 31 # 同源策略:为什么XMLHttpRequest不能跨域请求资源?

ajax之最简说明

Flink学习笔记:Flink的最简安装

springboot的最简创建方式

记录:Serilog的最简配置方法