Ajax使用过程中常见问题汇总
2011-03-13 00:00
801 查看
在看文章前,先指定一个通用的变量xhr,xhr代码ajax对象。测试浏览器:ie为ie6,firefox为2,其他的未测试。统称ie6为ie,firefox2为ff。
if(xhr.readystate==4)这种写法,在ie下是成立的,但是在ff下就行不通了,因为ie不区分大小写,ff是区分大小的。
标准写法为if(xhr.readyState==4),同理还有属性 responseText,responseXML。
直接拖进浏览器浏览结果或者双击运行html页面的,未发生错误时,此时的xhr.status是0,不是200。
所以可以多加一个xhr.status==0的判断。如下:
直接拖进浏览器浏览结果或者双击运行html页面时,又出现一个问题,如果请求的是xml文件,那想当然的是使用responseXML属性返回xmlDom了,但是在ie返回不了xmlDom属性,解决办法如何呢,看下面的responseXML问题。
在ie下有个问题,直接拖进浏览器浏览或者双击运行html预览效果时,请求的即使是xml文件,使用responseXML返回不了xmldom。
大家测试下就知道了,如下:
showbo.xml
test.html
解决办法就是使用microsoft.xmldom对象重新建立xml的树结构,如下
需要在open以后才能使用xhr.setRequestHeader方法,否则出错。
不久前放出的一个使用alexa,google的api获取alexa排名和google pr,分别使用了客户端和服务器端的xhr请求
中就是使用了服务器端的xhr请求,应为请求的是Google和alexa的页面,所以跨域了,需要使用服务器端的xhr请求。
meta声明的charset要和请求的页面返回的charset一致。最好在请求的页面中再设置下输出编码。
文件物理存储编码要和meta声明的编码要一致。如meta指定为gb2312,则物理存储编码为ansi。如果为utf-8,则要存储为utf-8编码。
对于asp,如果指定编码为utf-8,记得还要设置
因为asp在国内服务器默认处理编码为gb2312
为什么会出现这个问题呢??因为在执行getData中的代码var t=ajax_post(url,data);时,由于指定了异步,所以callServerByPost中的 http_request.send(data);//传送资料 这句话并不会中断其他js代码的执行,所以会继续执行getData中的下一句代码,就是alert(t),所以会出现undefined。
其实呢并不仅是ajax异步导致出现undefined的问题。认真看下代码var t=ajax_post(url,data);,t变量是接受的是ajax_post的返回值,但是ajax_post函数中并未使用return 返回任何值,所以默认是返回undefined。
你会说我这里不是使用了return http_request.responseText;//在这里明明调试时http_request.responseText已经有值但是在外边却接收不到返回了吗?大家看清楚了,那个是状态转换函数,你返回任何值是没有意义的,他只是处理ajax的状态,你返回值给谁用的呢?如何解决这个问题呢?一种是改为同步发送,一种就是为异步时使用全局变量来接受ajax的返回值,在状态转换函数中给全局变量赋值。
使用异步+全局变量时要注意的是在ajax未返回前千万不用使用全局变量,要不还是undefined。 下面给出同步的解决办法。异步+全局变量的解决方法看这篇文章
最后放自己写的ajax对象应用池程序
最经典的就是ie下的缓存问题了
如果使用的是get,那么在ie下出现缓存问题。导致代码只执行一次。解决办法就是加时间戳或者随机数,使url变为唯一,这样就不会出现ie下的缓存问题了,或者改为post提交。xhr.open("get","xxxx.aspx?_dc="+new Date().getTime(),true);
ajax对象属性的大小写问题
在w3c浏览器,如ff中,对大小写是敏感。如if(xhr.readystate==4)这种写法,在ie下是成立的,但是在ff下就行不通了,因为ie不区分大小写,ff是区分大小的。
标准写法为if(xhr.readyState==4),同理还有属性 responseText,responseXML。
ajax状态0问题
有些时候在测试 ajax 代码的时候,加了 xhr.status==200 的判断后,一直不执行 xhr.status==200 的代码,这个就需要注意了。xhr.status==200 是要通过服务器来浏览,并且服务器页面没有发生错误或者转向时才返回200状态的,此状态和你通过浏览器访问页面时服务器定义的状态一致。直接拖进浏览器浏览结果或者双击运行html页面的,未发生错误时,此时的xhr.status是0,不是200。
所以可以多加一个xhr.status==0的判断。如下:
if(xhr.status==200||xhr.status==0){ alert('ok'); }
直接拖进浏览器浏览结果或者双击运行html页面时,又出现一个问题,如果请求的是xml文件,那想当然的是使用responseXML属性返回xmlDom了,但是在ie返回不了xmlDom属性,解决办法如何呢,看下面的responseXML问题。
responseXML问题
要使用responseXML属性,请求的是xml文件或者设置了响应头为"text/xml"的动态页面了。要注意如果请求的是动态页面,一定不要忘记设置contenttype为"text/xml"!!!!!!!!切记~~~~~~asp为 response.contenttype="text/html" asp.net为 Response.ContentType="text/html"; php为 header("content-type:text/xml;");
在ie下有个问题,直接拖进浏览器浏览或者双击运行html预览效果时,请求的即使是xml文件,使用responseXML返回不了xmldom。
大家测试下就知道了,如下:
showbo.xml
<?xml version="1.0" encoding="utf-8"?> <showbo> <item>1</item> <item>2</item> <item>3</item> <item>4</item> </showbo>
test.html
function getajax(){ if(window.XMLHttpRequest)return new XMLHttpRequest(); else if(window.ActiveXObject)return new ActiveXObject("microsoft.xmlhttp"); } var xhr=getajax(); xhr.onreadystatechange=function(){ if(xhr.readyState==4){ if(xhr.status==200||xhr.status==0){ var doc=xhr.responseXML,item=doc.getElementsByTagName("item"); alert(item.length);//在ie输出为0,在ff下为4。似乎在ie下未生成xml的树结构,具体原因要问ms了。。 } else alert('发生错误\n\n'+xhr.status); } } xhr.open("get","showbo.xml?_dc="+new Date().getTime(),true); xhr.send(null);
解决办法就是使用microsoft.xmldom对象重新建立xml的树结构,如下
xhr.onreadystatechange=function(){ if(xhr.readyState==4){ if(xhr.status==200||xhr.status==0){ var doc=xhr.responseXML; if(document.all&&xhr.status==0){ //为ie并且直接托进浏览器的时重构xml的树结构 doc=new ActiveXObject("microsoft.xmldom"); doc.loadXML(xhr.responseText); doc=doc.documentElement; } var item=doc.getElementsByTagName("item"); alert(item.length);// } else alert('发生错误\n\n'+xhr.status); } }
为post提交时需要注意的
如果为post提交时,注意要设置content-type为"application/x-www-form-urlencoded",这样在动态页才可以使用request/request.form/request.querystring对象通过键获取值,否则得使用2进制数据,然后自己分析2进制数据生成字符串对象,使用正则什么的获取对应的值。需要在open以后才能使用xhr.setRequestHeader方法,否则出错。
xhr.open("post","xxxx.aspx",true); xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");//这里。。。。
跨域的问题
如果请求的页面不是当前站点的,那就跨域了,最好的解决方案就是服务器端的xhr请求不久前放出的一个使用alexa,google的api获取alexa排名和google pr,分别使用了客户端和服务器端的xhr请求
中就是使用了服务器端的xhr请求,应为请求的是Google和alexa的页面,所以跨域了,需要使用服务器端的xhr请求。
乱码问题
对于ajax应用来说,乱码也是一个经常出现的问题。meta声明的charset要和请求的页面返回的charset一致。最好在请求的页面中再设置下输出编码。
asp: response.charset="gb2312或者utf-8" asp.net: response.charset="gb2312或者utf-8" php: header("charset=gb2312或者utf-8")
文件物理存储编码要和meta声明的编码要一致。如meta指定为gb2312,则物理存储编码为ansi。如果为utf-8,则要存储为utf-8编码。
对于asp,如果指定编码为utf-8,记得还要设置
Session.CodePage=65001 Response.CharSet="utf-8"
因为asp在国内服务器默认处理编码为gb2312
同步问题
问题描述如下,问题来自http://topic.csdn.net/u/20090630/16/d4d07596-65da-430c-8e89-cae60e25e03c.html,精简了下创建ajax的代码function callServerByPost(url,data,fun) { var http_request=null; if (window.ActiveXObject)http_request = new ActiveXObject("Microsoft.XMLHTTP"); }else if (window.XMLHttpRequest) http_request = new XMLHttpRequest(); if (!http_request) { alert('Giving up :Cannot create an XMLHTTP instance'); return false; } http_request.onreadystatechange = fun; http_request.open("POST", url, true); http_request.setrequestheader("Content-length",data.length); http_request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); http_request.send(data);//传送资料 } function ajax_post(url,data) { url=url+"?t="+new Date(); callServerByPost(url,data,function fns(){ if(http_request.readyState == 4) { if (http_request.status == 200) { return http_request.responseText;//在这里明明调试时http_request.responseText已经有值但是在外边却接收不到 } else { alert("你请求数据有错"); } } }); } function getData(){ var url="ajax_server.aspx"; var data="name=ljp&pwd=ljp"; var t=ajax_post(url,data); alert(t);//在这里弹出undefined ============================= }
为什么会出现这个问题呢??因为在执行getData中的代码var t=ajax_post(url,data);时,由于指定了异步,所以callServerByPost中的 http_request.send(data);//传送资料 这句话并不会中断其他js代码的执行,所以会继续执行getData中的下一句代码,就是alert(t),所以会出现undefined。
其实呢并不仅是ajax异步导致出现undefined的问题。认真看下代码var t=ajax_post(url,data);,t变量是接受的是ajax_post的返回值,但是ajax_post函数中并未使用return 返回任何值,所以默认是返回undefined。
你会说我这里不是使用了return http_request.responseText;//在这里明明调试时http_request.responseText已经有值但是在外边却接收不到返回了吗?大家看清楚了,那个是状态转换函数,你返回任何值是没有意义的,他只是处理ajax的状态,你返回值给谁用的呢?如何解决这个问题呢?一种是改为同步发送,一种就是为异步时使用全局变量来接受ajax的返回值,在状态转换函数中给全局变量赋值。
使用异步+全局变量时要注意的是在ajax未返回前千万不用使用全局变量,要不还是undefined。 下面给出同步的解决办法。异步+全局变量的解决方法看这篇文章
function callServerByPost(url,data,fun) { var http_request=null; if (window.ActiveXObject)http_request = new ActiveXObject("Microsoft.XMLHTTP"); }else if (window.XMLHttpRequest) http_request = new XMLHttpRequest(); if (!http_request) { alert('Giving up :Cannot create an XMLHTTP instance'); return false; } // http_request.onreadystatechange = fun; //为同步时不再需要处理函数了。。。。。。。 http_request.open("POST", url, false);//改为同步 http_request.setrequestheader("Content-length",data.length); http_request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); http_request.send(data);//传送资料 return http_request.responseText;//同步时可以直接返回,因为会阻止其他的代码执行 } function ajax_post(url,data) { url=url+"?t="+new Date(); return callServerByPost(url,data,null);//不需要传递回调,并且直接返回callServerByPost的返回值 } function getData(){ var url="ajax_server.aspx"; var data="name=ljp&pwd=ljp"; var t=ajax_post(url,data); alert(t);//这里就不会输出undefined了。。。。。。。。。。。。,不过如果网路慢的话,浏览器就假死了。。 }
最后放自己写的ajax对象应用池程序
String.prototype.trim=function(){return this.replace(/$\s*|\s*$/g,'');} var Showbo={author:'showbo'}; //获取json对象 Showbo.getJson=function(v){if(typeof(v)=='string')return eval('('+v+')');else return v;} //根据id获取对象 Showbo.$=function(Id){if('object'==typeof(Id))return Id;else if('string'==typeof(Id))return document.getElementById(Id);else return null;} Showbo.IsIE=!!document.all; //扩展IE下的XMLHttpRequest if(Showbo.IsIE)window.XMLHttpRequest=function(){ var acX=['msxml2.xmlhttp.5.0','msxml2.xmlhttp.4.0','msxml2.xmlhttp.3.0','msxml2.xmlhttp','microsoft.xmlhttp'],Xhr; for(var i=0;itry{Xhr=new ActiveXObject(acX[i]);return Xhr;}catch(e){} return false; } //ajax应用池 Showbo.Ajax={ pools:[]//存储ajax对象的数组 ,getObject:function(){//从数组中获取ajax对象,如果未返回则新建一个ajax对象 for(var i=0;i<this.pools.length;i++) if(this.pools[i].readyState==0||this.pools[i].readyState==4)return this.pools[i]; this.pools[this.pools.length]=new XMLHttpRequest(); return this.pools[this.pools.length-1]; } ,send:function(cfg){/*cfg示例 { url:'请求的页面' ,params:'键值对,注意不是json对象' ,method:'post/get,如果为指定则默认为get' ,success:成功时的回调函数 ,failure:失败时的回调函数 ,otherParams:提供给回调函数的其他参数,可以为json对象 } 成功或者失败的回调函数参数为 (当前的xhr对象,配置文件的中的otherParams) */ if(!cfg||!cfg.url)throw("未设置配置文件!"); var method=cfg.method,asy="boolean"==typeof(cfg.asy)?cfg.asy:true; if(!method||method!="post")method="get"; if(method.toLocaleLowerCase()=='get'){ var _dc=new Date().getTime();//加时间戳防止ie浏览器下的缓存 cfg.params=cfg.params?cfg.params+'&_dc='+_dc:'_dc='+_dc; if(cfg.url.indexOf("?")!=-1)cfg.url+="&"+cfg.params; else cfg.url+="?"+cfg.params;cfg.params=null; } else if(!cfg.params)cfg.params=''; var o=this.getObject(); if(!o)throw("未能创建ajax对象!"); o.open(method,cfg.url,asy); if(method.toLocaleLowerCase()=='post')o.setRequestHeader("content-type","application/x-www-form-urlencoded"); o.send(cfg.params); o.onreadystatechange=function(){ if(o.readyState==4){ if(o.status==200||o.status==0){ if("function"==typeof(cfg.success))cfg.success(o,cfg.otherParams); } else if("function"==typeof(cfg.failure))cfg.failure(o,cfg.otherParams); } } } }
相关文章推荐
- Ajax技术(5)--Ajax使用过程中常见问题汇总
- CloudStack 安装及使用过程中常见问题汇总
- ubuntu下安装composer到使用composer安装laravel的过程及常见问题汇总
- spark2.0.1使用过程中常见问题汇总
- 使用Python+Selenium过程中中常见的问题汇总
- Unity3d使用过程中常见的20个问题
- 使用vs.net过程中问题汇总
- 一些主流IDE(VC6、VS2010、Code::Blocks、Eclipse)使用过程中常见问题集锦
- js Date对象以及使用过程中常见的问题
- iPod 使用过程中常见问题集锦
- D3.js使用过程中的常见问题(D3版本D3V4)
- Eclipse 使用常见问题汇总
- Eclipse使用时常见的问题(会在使用过程中继续补充的。。。。。)
- git 使用过程中常见问题
- 深入理解Spring Redis的使用 (五)、常见问题汇总
- 关于WebView的总结2---使用方法及常见问题和解决方案汇总
- 冷焊机使用过程中遇到的常见5大问题及解决办法
- 对于CocoaPods的简单理解,实践安装使用过程和常见问题
- freePBX使用及安装过程中的常见问题
- Android Studio 使用过程中出现的问题汇总(一)