2009-05-29

Ajax(XMLHttpRequest) 同步與非同步(異步)連結

首先針對 Internet Explorer 的連結物件做統一的處理,將 ActiveXObject 包裝成與 Mozilla 中的 XMLHttpRequest 相同的物件,這樣我們就可以排除瀏覽器的問題。

/* 針對不同瀏覽器的前置處理宣告 */
if (typeof(XMLHttpRequest)=="undefined" && window.ActiveXObject) {
XMLHttpRequest=function(){
var arrSignatures = [
"MSXML2.XMLHTTP.5.0",
"MSXML2.XMLHTTP.4.0",
"MSXML2.XMLHTTP.3.0",
"MSXML2.XMLHTTP",
"Microsoft.XMLHTTP"];
for (var i = 0; i < arrSignatures.length; i++) {
try{
var oRequest = new ActiveXObject(arrSignatures[i]);
return oRequest;
}catch(oError){/*ignore*/}
}
throw new Error("MSXML is not installed on your system.");
};
}



我們可以直接用 XMLHttpRequest 去處理 Ajax 連結,這是以[GET]方式建立[非同步]的傳送連接,如果要使用 POST 做連結請參考之前的文章[Ajax 使用 POST 傳送]。
POST 的差別只在於 open,setRequestHeader,send 這三個地方的設定。

/**=( 以[GET]方式建立[非同步]傳送連接 )====================*/

// 產生要求資料的 URL 及 GET 參數
var sURL = "check_in.php?user=xxxx&pass=xxxx";

// 建立 XMLHttpRequest 物件,並且送要求
var oRequest = new XMLHttpRequest();

// 設定連結方式及位址,並以非同步方式處理
oRequest.open("GET", sURL, true);
/*
void open(
in AUTF8String method, 傳送的方式
in AUTF8String url, 要求的位址
[optional] in boolean async, 同步方式(預設 true 非同步)
[optional] in AString user, 使用者名稱(預設為空字串)
[optional] in AString password 使用者密碼(預設為空字串)
);
*/

// 建立接收狀態的事件處理
oRequest.onreadystatechange = function(){
/*
當狀態變更時都會呼叫此事件
可利用 readyState 取得目前的狀態
所有可能的傳送狀態值如下:
0 (還沒開始)
1 (讀取中)
2 (已讀取)
3 (資訊交換中)
4 (請求完成)
*/
switch(oRequest.readyState){
case 0: // 開始前的程式處理
break;
case 1: // 讀取中的程式處理
break;
case 2: // 已讀取的程式處理
break;
case 3: // 資訊交換中的程式處理
break;
case 4: // 請求完成的程式處理
/* (在此處加入開啟已停用選項的設置) */

/*可以從responseText或responseXML取得傳回的資料*/
// 處理傳回為 200 的 HTTP 狀態碼
if (oRequest.status == 200) {
// 接受資料成功


// 將 responseText 中的文字轉成 JSON 物件
json = eval('('+oRequest.responseText+')');

// 處理其他錯誤 HTTP 狀態碼
}else{
/*接收資料失敗,可以從 statusText 取得錯誤狀態資訊*/
alert(oRequest.statusText);
}
break;
}

}

/* (在此處可以加入一些網頁選項停用的設置,以防止重複送出) */

// 送出 Ajax 要求
oRequest.send(null);
/*
以POST傳送時,這裡可以輸入(XML,串流,字串,JSON格式)
以GET傳送時,這裡只要輸入 null 或是空的
*/

// 強制中斷
//oRequest.abort();
/* 此函數方法可用在必要時,強制終止非同步請求 */



建立[同步]的 Ajax 傳送連接只要將 onreadystatechange 裡的程序移到 send 後面就可以了,如果非必要,最好還是不要以[同步]方式做連結,再處理死結的時候會多一些必要的處理,除非保證連結是 100% 正常且可行的。

/**=( 以[GET]方式建立[同步]傳送連接 )====================*/

// 產生要求資料的 URL 及 GET 參數
var sURL = "check_in.php?user=xxxx&pass=xxxx";

// 建立 XMLHttpRequest 物件,並且送要求
var oRequest = new XMLHttpRequest();

// 設定連結方式及位址,並以同步方式處理
oRequest.open("GET", sURL, false);
/*
void open(
in AUTF8String method, 傳送的方式
in AUTF8String url, 要求的位址
[optional] in boolean async, 同步方式(預設 true 非同步)
[optional] in AString user, 使用者名稱(預設為空字串)
[optional] in AString password 使用者密碼(預設為空字串)
);
*/

/* 開始前的程式處理... */

/* 讀取中的程式處理... */

// 送出 Ajax 要求
oRequest.send(null);
/*
以POST傳送時,這裡可以輸入(XML,串流,字串,JSON格式)
以GET傳送時,這裡只要輸入 null 或是空的
*/

// 請求完成的程式處理
/*可以從responseText或responseXML取得傳回的資料*/
// 處理傳回為 200 的 HTTP 狀態碼
if (oRequest.status == 200) {
// 接受資料成功

// 將 responseText 中的文字轉成 JSON 物件
json = eval('('+oRequest.responseText+')');

// 處理其他錯誤 HTTP 狀態碼
}else{
/*接收資料失敗,可以從 statusText 取得錯誤狀態資訊*/
alert(oRequest.statusText);
}



參考來源:
XMLHttpRequest - MDC
XMLHttpRequest的同步请求和Firefox的问题_网银

爪哇豆的秘密:AJAX深度歷險1(Getting Started)
Ajax内部交流文档
MoztwWiki:AJAX 上手篇
維基百科:AJAX
語言技術:Ajax Gossip

3 回應:

lucc 提到...

很實用的筆記,謝謝!

レイ 提到...

請問... 我在IE & Firefox的瀏覽器下都能正常執行,但是若是使用Google Chromium來檢視的話,在

//alert('XMLHttpRequest='+typeof XMLHttpRequest);
//alert('ActiveXObject='+window.ActiveXObject);

if (typeof XMLHttpRequest == "undefined" && window.ActiveXObject) {
function XMLHttpRequest2() {
....
}
}
XMLHttpRequest2()這段就會莫名奇妙地被呼叫來使用...(我故意放2在後面方便辨別~)
儘管我已用alert來確定 typeof XMLHttpRequest 以及 window.ActiveXObject都是不成立的
(typeof XMLHttpRequest=function & window.ActiveXObject=undefined)

是不是Google Chromium對於函式的優先使用順序跟其他瀏覽器不同?? 我快被搞瘋了...使用版本為:6.0.472.63

胡忠晞 Jax 提到...

Hi,レイ

我的確發現你所說的問題,現在在上面的範例我已經做了修正,並且也證實是可行的。