重複使用xmlhttprequest物件時的小問題

 Thu, 24 Jul 2008 19:34:03 +0800

這幾天自己重新寫一個小的ajax post工具,希望它可以同時存在多個實體,同一個實體也可以重複使用,但是在測試同一個實體重複使用時,發現了一個小問題。問題是在IE平台上出現的:

測試用的php,相當於echo,只是單純把post陣列印出:

print_r($_POST);

接下來是測試的網頁:

var fwajax = function() {
this.updating = false;
var query = {};
var thisref = this;
var ajax = (function() {
try{ return new ActiveXObject("Msxml2.XMLHTTP.3.0") }catch(e){}
try{ return new ActiveXObject("Msxml2.XMLHTTP") }catch(e){}
try{ return new ActiveXObject("Microsoft.XMLHTTP") }catch(e){}
try{ return new XMLHttpRequest();} catch(e){}
return null;
})();
function checkstate (callback) {
switch (ajax.readyState) {
case 1: break;
case 2: break;
case 3: break;
case 4:
callback(ajax.responseText,ajax.responseXML,ajax.status);
thisref.updating = false;
}
}
this.addQuery = function(name, value) {
query[encodeURIComponent(name)] = encodeURIComponent(value);
}
this.request = function(method, url, callback) {
try {
this.updating = true;
var qstr = "";
for(var i in query) {
qstr += i + "=" + query[i] + "&";
}
query = {};
ajax.onreadystatechange = function() {
checkstate(callback);
};
ajax.open(method, url, true);
ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
ajax.send(qstr);
}catch(e){alert(e);}
}
}
var a = new fwajax();
function test() {
if(!a.updating){
a.addQuery("key1","value1");
a.addQuery("key2","value2");
a.request("POST", "test279.php", function(a,b,c){alert(a);});
} else {
alert("updating!");
}
}

然後用一個按鈕處發test()。測試結果發現,第一次按下按鈕時沒問題,第二次按下按鈕就沒反應了。仔細檢查了一下,發現似乎onreadystatechange沒有觸發,或是沒有正確assign一個function做event handler。

經過稍為調整,發現有兩個方法可以修正:

  1. 把onreadystatechange的assign動作移到呼叫open()方法之後
  2. 使用新版的xml物件(除非是使用vista,使用者不一定會安裝msxml6.0...用處不大)

經過修改後,程式可以順利執行了:

var fwajax = function() {
this.updating = false;
var query = {};
var thisref = this;
var ajax = (function() {
try{ return new ActiveXObject("Msxml2.XMLHTTP.6.0") }catch(e){}
try{ return new ActiveXObject("Msxml2.XMLHTTP.3.0") }catch(e){}
try{ return new ActiveXObject("Msxml2.XMLHTTP") }catch(e){}
try{ return new ActiveXObject("Microsoft.XMLHTTP") }catch(e){}
try{ return new XMLHttpRequest();} catch(e){}
return null;
})();
function checkstate (callback) {
switch (ajax.readyState) {
case 1: break;
case 2: break;
case 3: break;
case 4:
callback(ajax.responseText,ajax.responseXML,ajax.status);
thisref.updating = false;
}
}
this.addQuery = function(name, value) {
query[encodeURIComponent(name)] = encodeURIComponent(value);
}
this.request = function(method, url, callback) {
try {
this.updating = true;
var qstr = "";
for(var i in query) {
qstr += i + "=" + query[i] + "&";
}
query = {};
ajax.open(method, url, true);
ajax.onreadystatechange = function() {
checkstate(callback);
};
ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
ajax.send(qstr);
}catch(e){alert(e);}
}
}
var a = new fwajax();
function test() {
if(!a.updating){
a.addQuery("key1","value1");
a.addQuery("key2","value2");
a.request("POST", "test279.php", function(a,b,c){alert(a);});
} else {
alert("updating!");
}
}

兩個方法都用上了,只是assign動作必須放在open()之後不太合理...(firefox就沒問題阿)