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 相关文章推荐
基于jQuery的固定表格头部的代码(IE6,7,8测试通过)
May 18 Javascript
jQuery点击自身以外地方关闭弹出层的简单实例
Dec 24 Javascript
Javascript实现鼠标右键特色菜单
Aug 04 Javascript
Javascript基础教程之比较null和undefined值
May 16 Javascript
分享jQuery封装好的一些常用操作
Jul 28 Javascript
如何编写jquery插件
Mar 29 jQuery
AngularJS中下拉框的高级用法示例
Oct 11 Javascript
浅谈AngularJs 双向绑定原理(数据绑定机制)
Dec 07 Javascript
vue-cli脚手架-bulid下的配置文件
Mar 27 Javascript
浅谈Angularjs中不同类型的双向数据绑定
Jul 16 Javascript
Vue常用的几个指令附完整案例
Nov 06 Javascript
微信小程序实现点击空白隐藏的方法示例
Aug 13 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
THINKPHP+JS实现缩放图片式截图的实现
2010/03/07 PHP
PHP开发规范手册之PHP代码规范详解
2011/01/13 PHP
PHP汉字转换拼音的函数代码
2015/12/30 PHP
php 中的closure用法详解
2017/06/12 PHP
laravel邮件发送的实现代码示例
2020/01/31 PHP
用Div仿showModalDialog模式菜单的效果的代码
2007/03/05 Javascript
一个js的tab切换效果代码[代码分离]
2010/04/11 Javascript
Json对象替换字符串占位符实现代码
2010/11/17 Javascript
JQuery DataTable删除行后的页面更新利用Ajax解决
2013/05/17 Javascript
一看就懂:jsonp详解
2015/06/01 Javascript
JavaScript中数据结构与算法(五):经典KMP算法
2015/06/19 Javascript
jquery实现鼠标滑过后动态图片提示效果实例
2015/08/10 Javascript
js电话号码验证方法
2015/09/28 Javascript
jquery插件jquery.LightBox.js实现点击放大图片并左右点击切换效果(附demo源码下载)
2016/02/25 Javascript
javascript基本算法汇总
2016/03/09 Javascript
JS简单实现浮动窗口效果示例
2016/09/07 Javascript
[原创]SyntaxHighlighter自动识别并加载脚本语言
2017/02/07 Javascript
BootStrap Table前台和后台分页对JSON格式的要求
2017/06/28 Javascript
jQuery简单实现对数组去重及排序操作实例
2017/10/31 jQuery
浅谈JavaScript面向对象--继承
2019/03/20 Javascript
vue中nextTick用法实例
2019/09/11 Javascript
如何构建一个Vue插件并生成npm包
2020/10/26 Javascript
[03:13]DOTA2-DPC中国联赛1月25日Recap集锦
2021/03/11 DOTA
Python下线程之间的共享和释放示例
2015/05/04 Python
Python字典实现简单的三级菜单(实例讲解)
2017/07/31 Python
django用户注册、登录、注销和用户扩展的示例
2018/03/19 Python
Python实现两个list求交集,并集,差集的方法示例
2018/08/02 Python
使用python Fabric动态修改远程机器hosts的方法
2018/10/26 Python
python 协程中的迭代器,生成器原理及应用实例详解
2019/10/28 Python
10分钟理解CSS3 FlexBox弹性布局
2018/12/20 HTML / CSS
Herve Leger官网:标志性绷带连衣裙等
2018/12/26 全球购物
什么是Web Service?
2012/07/25 面试题
大专毕业生自我鉴定
2013/11/21 职场文书
高职教师岗位职责
2013/12/24 职场文书
四风问题个人对照检查剖析材料
2014/09/27 职场文书
股权转让协议书
2014/12/07 职场文书