onreadyStateChange在Firefox中存在的差异

http://blog.csdn.net/stefanie860624/article/details/6221606 转载地址


在ajax应用中 出现的浏览器兼容问题 代码在IE中运行正常,在FF中出现异常经测试 readyState 的值始终为 1,在网上找了很多类似的问题尽管提问方式与重点各不相同,但是问题本身很多都是出在Firefox对onreadyStateChange的处理与IE在中存在的差异。在此做个总结

 

var xmlHttp = CreateXMLHttpRequest();
 
 if(xmlHttp){
  
  xmlHttp.open("GET",url,false)
  
  xmlHttp.onreadyStateChange = new function(){
   
   if (xmlHttp.readyState==4){
    sTable.innerHTML = xmlHttp.responseText; 
   }else{
    sTable.innerHTML = "正在加载.."+xmlHttp.readyState;
    //alert(""+showTab+"_"+url+"_"+showTab_id+"_"+xmlhttp.readyState);
   }
  }
  
  xmlHttp.send(null);



 

在ajax的XMLHttpRequest.onreadystatechange方法的差异:在FF中当状态为1(即XMLHttpRequest已经调用open但还没有调用send时),FF则会继续执行onreadystatechange后面的代码,到执行完后面的代码后,在执行onreadystatechange在状态2,3,4的代码,而IE会等待状态2的到了,执行完onreadystatechange中状态2,3,4的代码后,继续执行后面的代码,这样问题就出现了,经常我们在onreadystatechange的代码要处理从服务器上获得的数据(这个数据只有在onreadystatechange的状态为4时,才可以得到),所以这在IE中不存在问题,因为它会等待onreadystatechange状态4到来以后,在执行onreadystatechange后面的数据,但是由于FF不会等到onreadystatechange状态4到来后在执行onreadystatechange后面的代码,所以后面的代码就不能处理从服务器上获得的数据,那该怎么办呢? 我的解决办法是在send()之后再次调用了 onreadyStateChange 让他继续更新状态 直至 readyState==4

 

 

其他解决方法:

使用javascript的闭包(这个解决方法是从GMAP中获得灵感的)。我们传递一个函数给onreadystatechange,在这个函数中处理从服务器上返回的数据,但是onreadystatechange是一个无参函数,那该怎么办呢?方法在我前面的Javascript attachEvent传递参数的办法已经介绍 了,这里再稍微介绍一下,就是传递一个参数给onreadystatechange,但是在onreadystatechange中使用return一个无参函数,在这个无参函数中可以使用这个传入的参数。这个方法在IE和FF中都可以正常运行,所以这不失是一个好方法。 

 

 

 

参考用例代码:

<script type="text/javascript">
  //< ![CDATA[
  if(document.attachEvent){
    document.onreadystatechange=function(){
    //if(document.readyState=='interactive'){
      Start();
    //}
    };
  }
  else
  {
    document.addEventListener("DOMContentLoaded",Start,false);
  }
  function Start(){
    alert("document.readyState=" + document.readyState + "\nYes,I'm running");
  }//]]>
  </script>
  <p><img alt="walkingp" src="http://www.51obj.cn/demo/walkingp.jpg" /></p>


这里提到采用闭包,挺复杂,另外网上有采用了在FF下用onload,也是不管用。经过对错误排除,上面摘要提到的原因,才是根本的,也就是说,在FF下,第一次执行完onreadystatechange后,继续执行到send,但后面就不会再回头执行onreadystatechange,一直傻傻的走下去。
我直接改成:
   xmlHttp.onreadystatechange = xmlHandle;
   xmlHttp.open ("GET",Url,false);
   xmlHttp.send(null);
   xmlHttp.onreadystatechange = xmlHandle; //这里加一行挡住FF,让它再搞一次。


function xmlHandle(){
if (xmlHttp.readyState < 4){
       ......
}else if (xmlHttp.readyState == 4 && xmlHttp.status == 200){
   var cartResult = Number(xmlHttp.responseText);
    if (cartResult == 1){
      window.location.href='b.asp';
   }else if (cartResult == 2){
     ......;
   }else{
    window.location.href='/';
   }
}
}
但是这样也不行,原来ff 3改成:xmlHttp.onreadystatechange = xmlHandle();然而加了括号,IE又不行,唉,原来就觉得FF是鸡皮,现在感觉FF纯属一个打着“支持标准”的称号,却是干着浪费程序员时间的垃圾。但手上这个程序又实在重要,没办法,只有再调试看看有没有更简单的办法,如下:
   xmlHttp.open ("GET",Url,false);
   xmlHttp.send(null);
   if(xmlHttp.status==200)
      xmlHandle();
这段代码在IE和FF下可以通用。但由于是同步调用,需要在readyState<4时未取得结果前出现提示,这对于网速慢的客户很友好。然而要在本机获得这种等待反应时的情况,由于本机反应快,会造成看不到给客户提示,因此暂时先不用这个代码
只有加入浏览器类型分析。
function getOs()   
{   
   var OsObject = "";   
   if(navigator.userAgent.indexOf("MSIE")>0) {   
        return "MSIE";       //IE浏览器
   }
   if(isFirefox=navigator.userAgent.indexOf("Firefox")>0){   
        return "Firefox";     //Firefox浏览器
   }
   if(isSafari=navigator.userAgent.indexOf("Safari")>0) {   
        return "Safari";      //Safan浏览器
   }
   if(isCamino=navigator.userAgent.indexOf("Camino")>0){   
        return "Camino";   //Camino浏览器
   }
   if(isMozilla=navigator.userAgent.indexOf("Gecko/")>0){   
        return "Gecko";    //Gecko浏览器
   }   

然后把AJAX代码改为:
   var rndcode = new Date().getTime();
   var CartUrl ="a.asp?cache="+rndcode
   var btype=getOs();
   xmlHttp.onreadystatechange = (btype!="Firefox")?(xmlHandle):(xmlHandle());
   xmlHttp.open ("GET",CartUrl,false);
   xmlHttp.send(null);
   xmlHttp.onreadystatechange = (btype!="Firefox")?(xmlHandle):(xmlHandle());
总算OVER了,IE6、IE 7、FF通用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值