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 相关文章推荐
js 数组实现一个类似ruby的迭代器
Oct 27 Javascript
XENON基于JSON变种
Jul 27 Javascript
使用JavaScript获取地址栏参数的方法
Dec 19 Javascript
使用javascript实现Iframe自适应高度
Dec 24 Javascript
javascript中数组方法汇总
Jul 07 Javascript
Node.js实用代码段之获取Buffer对象字节长度
Mar 17 Javascript
jQuery webuploader分片上传大文件
Nov 07 Javascript
bootstrap vue.js实现tab效果
Feb 07 Javascript
JS实现双击内容变为可编辑状态
Mar 03 Javascript
浅谈基于Vue.js的移动组件库cube-ui
Dec 20 Javascript
layer弹出层扩展主题的方法
Sep 11 Javascript
javascript中call,apply,bind的区别详解
Dec 11 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+xslt在windows平台上
2006/10/09 PHP
PHP基于GD库的缩略图生成代码(支持jpg,gif,png格式)
2014/06/19 PHP
PHP使用PHPexcel导入导出数据的方法
2015/11/14 PHP
thinkPHP3.2.3实现阿里大于短信验证的方法
2018/06/06 PHP
javascript内存管理详细解析
2013/11/11 Javascript
Knockout数组(observable)使用详解示例
2013/11/15 Javascript
Jquery给基本控件的取值、赋值示例
2014/05/23 Javascript
AngularJS入门教程(一):静态模板
2014/12/06 Javascript
js鼠标点击按钮切换图片-图片自动切换-点击左右按钮切换特效代码
2015/09/02 Javascript
javascript高级编程之函数表达式 递归和闭包函数
2015/11/29 Javascript
实例详解JSON数据格式及json格式数据域字符串相互转换
2016/01/07 Javascript
JavaScript每天必学之数组和对象部分
2016/09/17 Javascript
JavaScript中英文字符长度统计方法示例【按照中文占2个字符】
2017/01/17 Javascript
详解小程序中h5页面onShow实现及跨页面通信方案
2019/05/30 Javascript
简单使用webpack打包文件的实现
2019/10/29 Javascript
JS实现滑动插件
2020/01/15 Javascript
JS实现图片幻灯片效果代码实例
2020/05/21 Javascript
vue - props 声明数组和对象操作
2020/07/30 Javascript
[54:09]RNG vs Liquid 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.23
2019/09/05 DOTA
Python中集合的内建函数和内建方法学习教程
2015/08/19 Python
Python实现数据库并行读取和写入实例
2017/06/09 Python
和孩子一起学习python之变量命名规则
2018/05/27 Python
python 读取竖线分隔符的文本方法
2018/12/20 Python
python requests使用socks5的例子
2019/07/25 Python
python 3.7.4 安装 opencv的教程
2019/10/10 Python
python文件读取失败怎么处理
2020/06/23 Python
windows支持哪个版本的python
2020/07/03 Python
python3 re返回形式总结
2020/11/20 Python
美国学校用品、教室和教学商店:Discount School Supply
2018/04/04 全球购物
乌克兰品牌化妆品和香水在线商店:Bomond
2020/01/14 全球购物
学生感冒英文请假条
2014/02/04 职场文书
分层教学实施方案
2014/03/19 职场文书
电子商务专业毕业生求职信
2014/06/12 职场文书
实习指导教师评语
2014/12/30 职场文书
推广普通话的宣传语
2015/07/13 职场文书
三八红旗手主要事迹材料
2015/11/04 职场文书