重複使用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。
經過稍為調整,發現有兩個方法可以修正:
- 把onreadystatechange的assign動作移到呼叫open()方法之後
- 使用新版的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就沒問題阿)