firefox下对ajax的onreadystatechange的支持情况分析


Posted in Javascript onDecember 14, 2009

一、问题:

var xmlHttp; 
function savecarttodata(){ 
createXMLHttpRequest(); 
var rndcode = new Date().getTime(); 
var CartUrl ="a.asp?cache="+rndcode 
xmlHttp.onreadystatechange = function(){ 
..... } 
xmlHttp.open ("GET",CartUrl,true); 
xmlHttp.send(null); 
}

上面的这段代码, xmlHttp.onreadystatechange = function(){.....};可以在FF下执行,但是如果改成

xmlHttp.open ("GET",Url,false);时就不行了,今天被这个问题整的晕头转向。

原因分析:

其一:这时不能用xmlHttp.send(),需要内容,如果没有内容,要用NULL

其二:经测试后发现,onreadystatechange在IE下都很正常,但在FF3下,只能运行readyState=0时的代码。不能运行readyState=4的代码,在网络上找了一个原因:
在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后面的代码,所以后面的代码就不能处理从服务器上获得的数据,那该怎么办呢?

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

这里提到采用闭包,挺复杂,另外网上有采用了在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='a.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;

例二
//获取游览器的类型,为解决onreadystatechange不兼容的问题 
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浏览器 
} 
} 
var objHttp; 
function searchCommodityByGroupId(groupId) 
{ 
objHttp = getHttpRequest(); 
var tt=new Date(); 
var url="getCommodityListByGroupId.htm?commodityGroupId="+groupId+"&time="+tt; 
var btype=getOs(); objHttp.onreadystatechange=(btype=="Firefox")?getCommodity():getCommodity; 
objHttp.open("GET",url,false); 
objHttp.send(null); 
objHttp.onreadystatechange=(btype=="Firefox")?getCommodity():getCommodity; 
} 
function getCommodity(){ 
if(objHttp.readyState==4) 
{ 
if(objHttp.status==200) 
{ 
document.getElementById("commodityDiv").innerHTML=objHttp.responseText; 
} 
} 
} 
function getHttpRequest(){ 
var httpRequest; 
if (window.XMLHttpRequest){ 
httpRequest = new XMLHttpRequest(); 
if (httpRequest.overrideMimeType){ 
httpRequest.overrideMimeType('text/xml'); 
} 
}else if (window.ActiveXObject){ 
try{ 
httpRequest = new ActiveXObject("Msxml2.XMLHTTP"); 
}catch(e){ 
try { 
httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); 
}catch(e){} 
} 
} 
return httpRequest; 
}
Javascript 相关文章推荐
全面解析Bootstrap排版使用方法(标题)
Nov 30 Javascript
js+html5操作sqlite数据库的方法
Feb 02 Javascript
JavaScript实现音乐自动切换和轮播
Nov 05 Javascript
用React-Native+Mobx做一个迷你水果商城APP(附源码)
Dec 25 Javascript
vue项目中公用footer组件底部位置的适配问题
May 10 Javascript
layui 数据表格复选框实现单选功能的例子
Sep 19 Javascript
js判断浏览器的环境(pc端,移动端,还是微信浏览器)
Dec 24 Javascript
原生js实现照片墙效果
Oct 13 Javascript
swiper4实现移动端导航栏tab滑动切换
Oct 16 Javascript
微信小程序自定义支持图片的弹窗
Dec 21 Javascript
全面解析js中的原型,原型对象,原型链
Jan 25 Javascript
8个JS的reduce使用实例和reduce操作方式
Oct 05 Javascript
javascript document.execCommand() 常用解析
Dec 14 #Javascript
JQuery Tips(3) 关于$()包装集内元素的改变
Dec 14 #Javascript
JQuery Tips(2) 关于$()包装集你不知道的
Dec 14 #Javascript
js 页面传参数时 参数值含特殊字符的问题
Dec 13 #Javascript
JQuery下关于$.Ready()的分析
Dec 13 #Javascript
javascript与asp.net(c#)互相调用方法
Dec 13 #Javascript
JavaScript 字符串与数组转换函数[不用split与join]
Dec 13 #Javascript
You might like
PHP通过session id 实现session共享和登录验证的代码
2012/06/03 PHP
PHP中创建图像并绘制文字的例子
2014/11/19 PHP
Ubuntu上安装yaf扩展的方法
2018/01/29 PHP
PHP PDOStatement::columnCount讲解
2019/01/30 PHP
PHP设计模式(三)建造者模式Builder实例详解【创建型】
2020/05/02 PHP
关于juqery radio写法的兼容性问题(新老版本jquery)
2010/06/14 Javascript
{}与function(){}选用空对象{}来存放keyValue
2012/05/23 Javascript
JS 屏蔽按键效果与改变按键效果的示例代码
2013/12/24 Javascript
jquery队列queue与原生模仿其实现方法分享
2014/03/25 Javascript
js与C#进行时间戳转换
2014/11/14 Javascript
javascript函数声明和函数表达式区别分析
2014/12/02 Javascript
移动Web中图片自适应的两种JavaScript解决方法
2015/06/18 Javascript
JavaScript、tab切换完整版(自动切换、鼠标移入停止、移开运行)
2016/01/05 Javascript
Jquery给当前页或者跳转后页面的导航栏添加选中后样式的实例
2016/12/08 Javascript
javascript实现简单的ajax封装示例
2016/12/28 Javascript
javaScript嗅探执行神器-sniffer.js
2017/02/14 Javascript
js获取指定时间的前几秒
2017/04/05 Javascript
浅谈react.js 之 批量添加与删除功能
2017/04/17 Javascript
AngularJS入门教程二:在路由中传递参数的方法分析
2017/05/27 Javascript
详解基于 Nuxt 的 Vue.js 服务端渲染实践
2017/10/24 Javascript
利用vue+elementUI实现部分引入组件的方法详解
2017/11/22 Javascript
Vue EventBus自定义组件事件传递
2018/06/25 Javascript
详解Vue.js使用Swiper.js在iOS
2018/09/10 Javascript
django项目运行因中文而乱码报错的几种情况解决
2017/11/07 Python
python读写LMDB文件的方法
2018/07/02 Python
Python分支语句与循环语句应用实例分析
2019/05/07 Python
Django框架基础模板标签与filter使用方法详解
2019/07/23 Python
详解Scrapy Redis入门实战
2020/11/18 Python
5分钟快速掌握Python定时任务框架的实现
2021/01/26 Python
暑假实习求职信范文
2013/09/22 职场文书
银行实习的自我鉴定
2013/12/10 职场文书
党员教师个人对照检查材料范文
2014/09/25 职场文书
2014年语文教师工作总结
2014/12/18 职场文书
让子弹飞观后感
2015/06/11 职场文书
践行三严三实心得体会(2016推荐篇)
2016/01/06 职场文书
mysql字段为NULL索引是否会失效实例详解
2022/05/30 MySQL