跨域的异步请求一
一直想搞一个强悍的异步系统,无奈各浏览器在这方面的实现林林总总,再加上跨域需求,就更复杂。现在我把我暂时能想到的东西都一点点写出来吧。
首先确定其参数,它大概和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); } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 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,谁才是开发者新宠?