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 之基础篇
Mar 24 Javascript
Jquery下:nth-child(an+b)的使用注意
May 28 Javascript
怎样在JavaScript里写一个swing把数据插入数据库
Dec 10 Javascript
node.js中的favicon.ico请求问题处理
Dec 15 Javascript
使用jQuery Mobile框架开发移动端Web App的入门教程
May 17 Javascript
bootstrap IE8 兼容性处理
Mar 22 Javascript
js-FCC算法-No repeats please字符串的全排列(详解)
May 02 Javascript
vue内置组件transition简单原理图文详解(小结)
Jul 12 Javascript
Element UI框架中巧用树选择器的实现
Dec 12 Javascript
微信小程序实现时间进度条功能
Nov 17 Javascript
react-router-dom 嵌套路由的实现
May 02 Javascript
JavaScript实现点击切换验证码及校验
Jan 10 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
我的论坛源代码(九)
2006/10/09 PHP
PHP教程 变量定义
2009/10/23 PHP
php实现将字符串按照指定距离进行分割的方法
2015/03/14 PHP
Yii2使用表单上传文件的实例代码
2017/08/03 PHP
PHP7新功能总结
2019/04/14 PHP
浏览器脚本兼容 文本框中,回车键触发事件的兼容
2010/06/21 Javascript
Js如何判断客户端是PC还是手持设备简单分析
2012/11/22 Javascript
javascript实现div浮动在网页最顶上并带关闭按钮效果实例
2013/08/13 Javascript
jQuery html()方法使用不了无法显示内容的问题
2014/08/06 Javascript
JavaScript判断表单中多选框checkbox选中个数的方法
2015/08/17 Javascript
JS将滑动门改为选项卡(需鼠标点击)的实现方法
2015/09/27 Javascript
浅谈JavaScript中的this指针和引用知识
2016/08/05 Javascript
express文件上传中间件Multer详解
2016/10/24 Javascript
JavaScript实现类似拉勾网的鼠标移入移出效果
2016/10/27 Javascript
Node.js通过身份证号验证年龄、出生日期与性别方法示例
2017/03/09 Javascript
javascript获取图片的top N主色值方法详解
2018/01/26 Javascript
判断iOS、Android以及PC端的示例代码
2018/11/15 Javascript
Vue.js结合bootstrap前端实现分页和排序效果
2018/12/29 Javascript
微信小程序用户授权弹窗 拒绝时引导用户重新授权实现
2019/07/29 Javascript
python 随机数生成的代码的详细分析
2011/05/15 Python
python在linux中输出带颜色的文字的方法
2014/06/19 Python
Django集成CAS单点登录的方法示例
2019/06/10 Python
django 通过url实现简单的权限控制的例子
2019/08/16 Python
wxPython实现带颜色的进度条
2019/11/19 Python
五种Python转义表示法
2020/11/27 Python
纯css3使用vw和vh实现自适应的方法
2018/02/09 HTML / CSS
uniapp+Html5端实现PC端适配
2020/07/15 HTML / CSS
法国一家芭蕾舞鞋公司:Repetto
2018/11/12 全球购物
Shell如何接收变量输入
2012/09/24 面试题
测控技术与通信工程毕业生自荐信范文
2013/12/28 职场文书
甜品店的创业计划书范文
2014/01/02 职场文书
六查六看个人剖析材料
2014/10/14 职场文书
夫妻分居协议书范本
2014/11/28 职场文书
帝企鹅日记观后感
2015/06/10 职场文书
使用Python的开发框架Brownie部署以太坊智能合约
2021/05/28 Python
室外天线与收音机天线杆接合方法
2022/04/05 无线电