FireFox對ajax的onreadystatechange的支持
來源:程序員人生 發布時間:2013-11-09 09:52:57 閱讀次數:2708次
一、問題:
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;
}
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈