Ruby's Louvre

每天学习一点点算法

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

跨域的异步请求一

一直想搞一个强悍的异步系统,无奈各浏览器在这方面的实现林林总总,再加上跨域需求,就更复杂。现在我把我暂时能想到的东西都一点点写出来吧。

首先确定其参数,它大概和Greasemonkey的GM_xmlhttpRequest一个样子。

dom.ajax({
  method:"GET",//HTTP 请求类型,get post delete put
  url:location.href,//必须是绝对路径
  headers:{"Content-Type": "application/x-www-form-urlencoded"},//首部,对象字面量
  overrideMimeType:"text/html; charset=ISO-8859-1",
  data:null,//传到后面的数据
  onerror:function(){},//请求错误时的回调函数
  onload:function(){}//请求成功时的回调函数
});

然后就是内部实现了,暂时不考虑跨域,是这个样子:

dom.ajax = function(opts){
  var s = dom.mixin(true,{},dom.ajaxSettings,opts),
  method = s.method.toUpperCase(),
  xhr = dom.xhr();
  if ( s.username ) {
    xhr.open(method, s.url, s.async, s.username, s.password);
  } else {
    xhr.open(method, s.url, s.async);
  }
  xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
  xhr.onreadystatechange = function () {
    if (xhr.readyState == 4){
        //   alert(xhr.responseText)
    }
  };
  xhr.send(opts.data || null);
}

接着是对各个细节进行强化,如对传输数据的处理,为url添加参数,缓存的设置,首部的设置等等……

一般地,我们提交表单时,会将表单元素的name与value,转换为“name1=value1?name2=value2”这种形式,如果是post请求,则放到send方法中,如果是get方法,则置于url之后。另,如果method不为get或post,我们需要用post来模拟它。有时,我们还会自行添加一些特别标识的数据进行请求,如一些大公司的查询服务(IP查询,RSS订阅,天气预报)。为了放便处理对象,我们必要时将它转换为一个对象,到发送请求时再变回字符串:

query = dom.isString(obj.data) ? dom.ajax.toQueryObject(obj.data) : obj.data || {}
if(/get|post/i.test(method)){
    query._method = method;
    method = obj.method = "POST"
}
query = dom.ajax.toQueryString(query)

缓存的处理,这个有好有坏,如果是测试阶段,我们可以设置一个首部If-Modified-Since为0。对于get请求,我们还可以加个时间截或随机数什么的。

首部的设置,它一定要在调用了open方法才能用:

setRequestHeaders:function(xhr,obj){//AJAX对象与参数对象
    var headers = {
        "Accept" : obj.accepts[ obj.dataType ] ? obj.accepts[ obj.dataType ] + ", */*" : obj.accepts._default ,
        "X-Requested-With": "XMLHttpRequest"
    }
    if(!obj.cache){
        headers["If-Modified-Since"] = "0"
    }
    dom.mixin(headers,obj.headers)
    if (obj.method === 'POST') {
        headers['Content-type'] = obj.contentType +  '; charset=' + obj.encoding ;
        if (xhr.overrideMimeType &&
            (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
            headers['Connection'] = 'close';
    }
    for(var i in headers){
        xhr.setRequestHeader(i,headers[i]);
    }
}

timeout与abort处理,由于这两个方法在各浏览器的支持程度都不一样,做得最好的是IE8的XDomainRequest与XMLHttpRequest。

var xhr = dom.xhr();
xhr.open("POST",location.href,true);
xhr.onreadystatechange=function(){
  if (xhr.readyState == 4 && xhr.status == 200) {
    clearTimeout(xhrTimeout);
    alert(xhr.responseText);
  }
}
xhr.send("ruby louvre");
var xhrTimeout=setTimeout("ajaxTimeout();",5000);
function ajaxTimeout(){
  xhr.abort();
  alert("强制关闭链接!");
}

不过为了兼容所有浏览器,最廉价的方法还是JSONP,具体可参看这一篇文章:《クロスドメイン通信方法のまとめ》

function jsonp(url,callback,name, query){               
    if (url.indexOf("?") !== -1)
        url += "&jsonp="
    else
        url += "?jsonp="
    url += name + "&";
    if (query)
        url += encodeURIComponent(query) + "&";  
    url += (new Date-0); // prevent caching       
     
    var script = document.createElement("script");       
    script.setAttribute("src",url);
    script.setAttribute("type","text/javascript");               
    document.body.appendChild(script);
}

如果您觉得此文有帮助,可以打赏点钱给我支付宝1669866773@qq.com ,或扫描二维码

posted on   司徒正美  阅读(4524)  评论(12编辑  收藏  举报

编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
点击右上角即可分享
微信分享提示