1. 程式人生 > >XHR的用法詳細解讀

XHR的用法詳細解讀

在使用XHR物件時,要呼叫的第一個方法是 open(),它接受 3個引數:要傳送的請求的型別(”get”、”post”等)、請求的URL和表示是否非同步傳送請求的布林值。下面就是呼叫這個方法的例子。

xhr.open("get", "example.php", false);

這行程式碼會啟動一個針對example.php的GET請求。有關這行程式碼,需要說明兩點:一是URL 相對於執行程式碼的當前頁面(當然也可以使用絕對路徑);二是呼叫open()方法並不會真正傳送請求,而只是啟動一個請求以備傳送。

只能向同一個域中使用相同埠和協議的URL傳送請求。如果URL與啟動請求的頁面有任何差別,都會引發安全錯誤。

要傳送特定的請求,必須像下面這樣呼叫send()方法:

xhr.open("get", "example.txt", false);
xhr.send(null);

這裡的send()方法接收一個引數,即要作為請求主體傳送的資料。如果不需要通過請求主體傳送資料,則必須傳入null,因為這個引數對有些瀏覽器來說是必需的。呼叫send()之後,請求就會被分派到伺服器。

由於這次請求是同步的,JavaScript程式碼會等到伺服器響應之後再繼續執行。在收到響應後,響應的資料會自動填充XHR物件的屬性,相關的屬性簡介如下。

responseText:作為響應主體被返回的文字。
responseXML:如果響應的內容型別是"text/xml"或"application/xml",這個屬性中將儲存包含著響應資料的XML DOM文件。  
status:響應的HTTP狀態。
statusText:HTTP狀態的說明。

在接收到響應後,第一步是檢查status屬性,以確定響應已經成功返回。一般來說,可以將HTTP 狀態程式碼為200作為成功的標誌。此時,responseText屬性的內容已經就緒,而且在內容型別正確的情況下,responseXML也應該能夠訪問了。此外,狀態程式碼為304表示請求的資源並沒有被修改,可以直接使用瀏覽器中快取的版本;當然,也意味著響應是有效的。為確保接收到適當的響應,應該像下面這樣檢查上述這兩種狀態程式碼:

xhr.open("get", "example.txt", false);
xhr.send(null);
if ((xhr.status >= 200 && xhr.status
< 300) || xhr.status == 304){ alert(xhr.responseText); } else { alert("Request was unsuccessful: " + xhr.status); }

根據返回的狀態程式碼,這個例子可能會顯示由伺服器會顯示一條錯誤訊息。我們建議讀者要通過檢測status來決定下一步的操作,不要依賴statusText,因為後者在跨瀏覽器使用時不太可靠。另外,無論內容型別是什麼,響應主體的內容都會儲存到responseText屬性中;而對於非XML資料而言responseXML屬性的值將為null。

像前面這樣傳送同步請求當然沒有問題,但多數情況下,我們還是要傳送非同步請求,才能讓JavaScript繼續執行而不必等待響應。此時,可以檢測XHR物件的readyState屬性,該屬性表示請求/響應過程的當前活動階段。這個屬性可取的值如下。

0:未初始化。尚未呼叫open()方法。
1:啟動。已經呼叫open()方法,但尚未呼叫send()方法。
2:傳送。已經呼叫send()方法,但尚未接收到響應。
3:接收。已經接收到部分響應資料。
4:完成。已經接收到全部響應資料,而且已經可以在客戶端使用了。

只要readyState屬性的值由一個值變成另一個值,都會觸發一次readystatechange事件。可以利用這個事件來檢測每次狀態變化後readyState的值。通常,我們只對readyState值為4的階段感興趣,因為這時所有資料都已經就緒。不過,必須在呼叫open()之前指定onreadystatechange事件處理程式才能確保跨瀏覽器相容性。下面來看一個例子。

    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function(){
        if (xhr.readyState == 4){
            if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
                alert(xhr.responseText);
            } else {
                alert("Request was unsuccessful: " + xhr.status);
            }
        }
    };
    xhr.open("get", "example.txt", true);
    xhr.send(null);

以上程式碼利用DOM 0級方法為XHR物件添加了事件處理程式,原因是並非所有瀏覽器都支援DOM 2級方法。與其他事件處理程式不同,這裡沒有向onreadystatechange事件處理程式中傳遞event物件;必須通過XHR物件本身來確定下一步該怎麼做。

這個例子在onreadystatechange事件處理程式中使用了xhr物件,沒有使用this物件,原因是onreadystatechange事件處理程式的作用域問題。如果使用this物件,在有的瀏覽器中會導致函式執行失敗,或者導致錯誤發生。因此,使用實際的XHR物件例項變數是較為可靠的一種方式。

另外,在接收到響應之前還可以呼叫abort()方法來取消非同步請求,如下所示:

xhr.abort();    

呼叫這個方法後,XHR物件會停止觸發事件,而且也不再允許訪問任何與響應有關的物件屬性。在終止請求之後,還應該對XHR物件進行解引用操作。由於記憶體原因,不建議重用XHR物件