ff對ajax的onreadystatechange的支援

來源:互聯網
上載者:User

一、問題:

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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.