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

一、问题:

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;
} 

我觉得那个判断各个浏览器的有些多余,直接只判断火狐吧,如下

var browserflag=0;
if(isFirefox=navigator.userAgent.indexOf("Firefox")>0){
browserflag=1
}
xmlHttp.onreadystatechange = (browserflag!=1)?(serverResponse):(serverResponse());
xmlHttp.open ("GET","taogogo.py",false);
xmlHttp.send(null);
xmlHttp.onreadystatechange = (browserflag!=1)?(serverResponse):(serverResponse());

上面为查找资料得到

但是还是不行!!!

var xmlhttp = loadXMLDoc();
var startRequestMethod = function(obj){
    var url = "http://www.xxxx.com?id=1";
    xmlhttp.open("get", url, false);    //这是个同步请求
    xmlhttp.send(null);
    xmlhttp.onReadyStateChange = stateChange;  //注意这儿
}  

var stateChange = function(){
    if(xmlhttp.readyState == 4){
       if (xmlhttp.status == 200){
            //需要执行的代码
       }else{
            alert("操作失败!");
       }
    }
}  

var loadXMLDoc = function(){
  var xmlhttp = null;
  if(window.XMLHttpRequest){
      xmlhttp = new XMLHttpRequest();
  }else if (window.ActiveXObject){
      xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  }
  return xmlhttp;
}  

查了资料后发现,FireFox3下同步请求不需要等待onReadyStateChange,而直接执行后续代码,于是只要将原先代码中

xmlhttp.onReadyStateChange = stateChange;    这句注掉,然后直接调用stateChange()方法。代码如下:

var startRequestMethod = function(obj){
    var url = "http://www.xxxx.com?id=1";
    xmlhttp.open("get", url, false);    //这是个同步请求
    xmlhttp.send(null);
    //xmlhttp.onReadyStateChange = stateChange;  //注意这儿
    stateChange();
}  

综合上面的,可以对同步和异步请求做个判断,做个通用化的处理,代码如下:

var startRequestMethod = function(obj){
    var url = "http://www.xxxx.com?id=1";
    var ansyType = true; //默认异步
    xmlhttp.open("get", url, ansyType); //这是个同步请求
    xmlhttp.send(null);
    if(ansyType){  //异步
       xmlhttp.onReadyStateChange = stateChange;
    }else{         //同步
       stateChange();
    }
}  

最后,上传自己写的

乱了点,但是至少是个总结

$("#changeCoupon").click(function () {
                var couponVal = $("#selQuans").val();
                var ary = couponVal.split("$");
                var couponType = ary[0];
                var parValue = ary[1];
                if (couponType == "") {
                    alert("请选择优惠券类别");
                    $("#selQuans").focus();
                    return;
                }
                var consumedIntegral = $(‘#jifen‘).val();
                var canUseIntergral = $(‘#lab_jifen‘).text();
                if (parseInt(canUseIntergral) < parseInt(consumedIntegral)) {
                    alert("抱歉您的积分还不够兑换该券");
                    $("#selQuans").focus();
                    return;
                }
                var postdata = { coupontype: couponType, parvalue: parValue, consumedintegral: consumedIntegral };
                //最起初方法
                //$.post("services/Integral2Coupon.ashx", postdata, function (json) {
                //     if (json.error_code == 0) {
                //     var integralLogList = $("#tab0\\.page0");
                //     var tpl = $("#integrallogtpl").html();
                //     var html = _.template(tpl, json.data.integralLog);
                //     integralLogList.append(html);

                //     var couponlist = $("#tb0\\.pg0");
                //     tpl = $("#coupontpl0").html();
                //     html = _.template(tpl, json.data.coupon);
                //     couponlist.append(html);

                //     var integraltocouponList = $("#tab0\\.page1");
                //     tpl = $("#integraltocoupontpl").html();
                //     html = _.template(tpl, json.data.integralToCoupon);
                //     integraltocouponList.append(html);

                //        alert("积分换券成功!")
                //     }
                //     else
                //        alert(json.data.msg)
                //     });

                //09-01 改变 ajax 方式 采用判断浏览器改同步或异步方式 strat
                var browserflag = 0;
                var ansyType = true; //默认异步
                if (isFirefox = navigator.userAgent.indexOf("Firefox") > 0) {
                    browserflag = 1;
                    ansyType = false;
                }
                var args = "coupontype=" + couponType + "&parvalue=" + parValue + "&consumedintegral=" + consumedIntegral;
                var xmlhttp;
                if (window.XMLHttpRequest) {
                    //如果为 Mozilla,Safari 等浏览器
                    xmlhttp = new XMLHttpRequest();
                    if (xmlhttp.overrideMimeType)
                        xmlhttp.overrideMimeType(‘text/xml‘);
                }
                else if (window.ActiveXObject) {    //如果是Ie浏览器
                    try {
                        xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
                    }
                    catch (e) {
                        try {
                            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
                        }
                        catch (e) { }
                    }
                }
                var url = "services/Integral2Coupon.ashx";
                //xmlhttp.onreadystatechange = (browserflag != 1) ? serverResponse() : serverResponse;
                xmlhttp.open("POST", url, ansyType);
                xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
                xmlhttp.send(args);
                if (ansyType) {  //异步
                    xmlhttp.onReadyStateChange = stateChange;
                } else {         //同步
                    stateChange();
                }
                //xmlhttp.onreadystatechange = (browserflag != 1) ? serverResponse() : serverResponse;
                function serverResponse() {
                    if (xmlhttp.readyState == 4) //readyState == 4 表示服务器返回完成数据了。之前可能会经历2(请求已发送,正在处理中)、3(响应中已有部分数据可用了,但是服务器还没有完成响应的生成)
                    {
                        if (xmlhttp.status == 200) //如果状态码为200则是成功
                        {
                            //onsuccess(xmlhttp.responseText);
                            //var json = JSON.parse(xmlhttp.responseText);

                            var jsons = xmlhttp.responseText;
                            var json;
                            if (typeof (JSON) == ‘undefined‘) {
                                json = eval("(" + jsons + ")");
                            } else {
                                json = JSON.parse(jsons);
                            }

                            if (json.error_code == 0) {
                                var integralLogList = $("#tab0\\.page0");
                                var tpl = $("#integrallogtpl").html();
                                var html = _.template(tpl, json.data.integralLog);
                                integralLogList.append(html);

                                var couponlist = $("#tb0\\.pg0");
                                tpl = $("#coupontpl0").html();
                                html = _.template(tpl, json.data.coupon);
                                couponlist.append(html);

                                var integraltocouponList = $("#tab0\\.page1");
                                tpl = $("#integraltocoupontpl").html();
                                html = _.template(tpl, json.data.integralToCoupon);
                                integraltocouponList.append(html);

                                alert("积分换券成功!")
                            }
                            else
                                alert(json.data.msg)

                        }
                        else {
                            alert("AJAX服务器返回错误!");
                        }
                    }
                };
                //ajax end
            });
时间: 2024-07-28 13:47:32

firefox下对ajax的onreadystatechange的支持情况分析及解决的相关文章

分享下今天研究的流量上限DDos攻击分析和解决方式

分享下今天研究的流量上限DDos攻击分析和解决方式 常常听到或者碰到某个站点被攻击.一般都是流量攻击.今天自己写了个程序測下相关的上限,程序仅仅简单做了个get html操作(不包括图片等资源文件). 用一台双核CPU机器A,启100个线程,连续发送serverB.统计出的结果是每秒钟发173个请求,机器A的发送带宽450Kbps,机器A的接收带宽2.8Mbps,机器B的发送带宽2.8Mbps,机器B的接收带宽450Kbps. 用一台双核CPU机器A,启1000个线程,连续发送serverB,统

firefox下jquery ajax 返回 [object XMLDocument]处理

1 在firefox下使用jquery ajax处理 返回json类型的时候,ajax执行成功返回结果为 [object XMLDocument]. 2 3 处理办法:在getWriter.write():前面加上一行代码response().setContentType("text/html;charset=UTF-8");

FontAwesome在Firefox下建立静态页面不显示的情况

1.在相对路径时发现firefox的问题(但是在Chrome下没有问题),还需进一步确认. 最开始是直接把FontAwesome的less直接替换掉Bootstrap的glyphicons字体,编译后在firefox下一直是不显示,经过单独引用FontAwesome的css及font才发现如果换成第14行的路径写法是可以正常显示的,如图: 2.情景描述 以往做静态页面原型的文件的文件结构是这样的: folder |----css |----images |----js index.html ..

JS的六大对象:Global、Math、Number、Date、JSON、console,运行在服务器上方的支持情况分析

在ASP中使用runat="server"来调用JS的相关函数,代码如下: <script runat="server" language="javascript"> // 代码部份 </script> 下表列举JS六大对象在runat="server"中的支持情况: 对象 是否支持 Global 支持 Math 支持 Number 支持 Date 不支持 JSON 不支持 console 不支持 原文

AR8033 1000M模式下ping包丢包率过大分析与解决

1 现象 近期对一款基于QCA方案.有线Phy为AR8033.WiFi双频且支持iEEE802.11AC的WLAN产品进行了深度验证,发现有线口同部分PC机直连时,WiFi终端ping 该PC机时总是丢包,有时高达20%:但通过交换机再接PC机时,又不会丢包.一直以为是偶现,所以未引起重视,反正跑流性能与稳定性都没有任何影响.后来新购了一批千兆有线口的便携机进行配套验证时,发现每台都是如此,ping包丢得一塌涂地.在WLAN设备和PC机上分别开启抓包工具,可以看到设备已发包,但PC机未收到报文:

[转]IE9.0或者360下js(JavaScript、jQuery)不能正确执行(加载),按F12后执行正常;Firefox下ajax的success返回数据data(json、string)无法获取

兼容问题1: 页面的分享等插件加载不全,并无法点击. 兼容问题2: IE下页面选择器(#id..class.etc.)绑定click事件无法访问到,后台springmvc方法,也无法获取ajax的success方法返回值data. 兼容问题3: 在IE和Google下能够获取,ajax的success返回的数据data,但firefox下获取不到. 兼容问题4: 页面跳转,或url进入,js代码不能正确执行,如果按了F12后(开启F12),JavaScript(加载)事件可以正常响应,一切都正常

嵌入式开发——boa服务器下的ajax与cgi通信

博主最近在最有做一个嵌入式课程设计,要求是利用基于cortax a8的物联网实验箱做一个简单的嵌入式网页交互系统作为课程设计来验收评分.因为本身自己是学前端的,所以网页部分并不是重点,主要是和boa服务器之间的通信,课程实验给的例子是直接使用printf来打印html标签形成新的页面,有过前端开发经验的人都知道这种做法效率低下而且没有办法实现异步刷新,所以博主采用ajax来进行boa服务器下的异步通信. 主要实现及踩过的坑如下: 1. get 还是 post请求:怎么发请求参见W3School上

xmlHttpRequest在Firefox下不起作用?

描述: xmlHttpRequest 在IE下正常,在Firefox下不起作用. 原因: xmlHttpRequest 对象的 onreadychange 不会在Firefox下执行, 解放方法: 使用 jQuery 实现 AJAX 去代替 xmlHttpRequest.

IE和Firefox下的Cookie兼容问题

这个帖是继于"基于二级域名下Cookie共享的SSO"后续发现的问题,测试结果是这样的:用Firefox可以登录,使用IE后,部分可以登录,部分不可以登录.最初是怀疑IE的Cookie功能没有打开引起的,测试到最后这个原因也排除了. 既然是通过Cookie实现SSO,那认证必然是保存在Cookie中,Cookie文件就是保存在本地的缓 存目录下(firefox下的Cookie是加密的,查不到Cookie文件),但是奇怪的是IE登录后,缓存目录下根本没有发现生成的Cookie文 件,这就