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 相关文章推荐
利用Dojo和JSON建立无限级AJAX动态加载的功能模块树
Mar 24 Javascript
js查找父节点的简单方法
Jun 28 Javascript
html+css+js实现xp window界面及有关功能
Mar 26 Javascript
javascript和HTML5利用canvas构建猜牌游戏实现算法
Jul 17 Javascript
基于JavaScript实现跳转提示页面
Sep 24 Javascript
详解vue-cli中配置sass
Jun 21 Javascript
基于rem的移动端响应式适配方案(详解)
Jul 07 Javascript
JavaScript代码执行的先后顺序问题
Oct 29 Javascript
Bootstrap实现的表格合并单元格示例
Feb 06 Javascript
axios简单实现小程序延时loading指示
Jul 30 Javascript
JavaScript命名空间模式实例详解
Jun 20 Javascript
Vue简单封装axios之解决post请求后端接收不到参数问题
Feb 16 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
?繁体转换的class
2006/10/09 PHP
php配合jquery实现增删操作具体实例
2013/12/12 PHP
php通过文件流方式复制文件的方法
2015/03/13 PHP
php实现图片等比例缩放代码
2015/07/23 PHP
php支持断点续传、分块下载的类
2016/05/02 PHP
PHP 根据key 给二维数组分组
2016/12/09 PHP
php中Ioc(控制反转)和Di(依赖注入)
2017/05/07 PHP
PHP判断函数是否被定义的方法
2019/06/21 PHP
PHP7修改的函数
2021/03/09 PHP
JS target与currentTarget区别说明
2011/08/28 Javascript
JavaScript Memoization 让函数也有记忆功能
2011/10/27 Javascript
javascript实现10个球随机运动、碰撞实例详解
2015/07/08 Javascript
js实现滚动条滚动到页面底部继续加载
2015/12/19 Javascript
JavaScript修改作用域外变量的方法
2016/03/25 Javascript
JS实现显示带倒影的图片横排居中放大展示特效实例【测试可用】
2016/08/23 Javascript
js实现颜色阶梯渐变效果(Gradient算法)
2017/03/21 Javascript
jquery图片放大镜效果
2017/06/23 jQuery
angularjs2 ng2 密码隐藏显示的实例代码
2017/08/01 Javascript
JS返回顶部实例代码
2020/08/09 Javascript
Angular4集成ng2-file-upload的上传组件
2018/03/14 Javascript
VUE搭建手机商城心得和遇到的坑
2019/02/21 Javascript
详解vue配置后台接口方式
2019/03/29 Javascript
arctext.js实现文字平滑弯曲弧形效果的插件
2019/05/13 Javascript
Vue的状态管理vuex使用方法详解
2020/02/05 Javascript
vuex的使用和简易实现
2021/01/07 Vue.js
[01:33]完美世界DOTA2联赛PWL S3 集锦第二期
2020/12/21 DOTA
python中redis的安装和使用
2016/12/04 Python
快速了解Python中的装饰器
2018/01/11 Python
解决django后台样式丢失,css资源加载失败的问题
2019/06/11 Python
jupyter 中文乱码设置编码格式 避免控制台输出的解决
2020/04/20 Python
Pycharm打开已有项目配置python环境的方法
2020/07/03 Python
python实现scrapy爬虫每天定时抓取数据的示例代码
2021/01/27 Python
欧铁通票官方在线销售网站:Eurail.com
2017/10/14 全球购物
优瑞自动咖啡机官网:Jura
2018/09/29 全球购物
焊接专业毕业生求职信
2013/10/01 职场文书
奖学金申请个人主要事迹材料
2015/11/04 职场文书