XMLHttpRequest 對象是AJAX功能的核心,要開發AJax程序必須從了解XMLHttpRequest 對象開始。
了解XMLHttpRequest 對象就先從創建XMLHttpRequest 對象開始,在不同的浏覽器中創建XMLHttpRequest 對象使用不同的方法:
先看看IE創建XMLHttpRequest 對象的方法(方法1):
var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
//使用較新版本的 IE 創建 IE 兼容的對象(Msxml2.XMLHTTP)
var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
//使用較老版本的 IE 創建 IE 兼容的對(Microsoft.XMLHTTP)
var xmlhttp = new XMLHttpRequest();
實際上Internet Explorer 使用了一個名為 XMLHttp 的對象,而不是 XMLHttpRequest 對象,而 Mozilla、Opera、Safari 和 大部分非 Microsoft 浏覽器都使用的是後者(下文統稱 XMLHttpRequest 對象)。IE7開始也開始使用XMLHttpRequest 對象了。
在創建 XMLHttpRequest 對象的時候如果不同的浏覽器使用了不正確的方法浏覽器都將會報錯,並且無法使用該對象。所以我們需要一種可以兼容不同浏覽器的創建XMLHttpRequest 對象的方法:
創建兼容多浏覽器的 XMLHttpRequest 對象方法
var xmlhttp = false; //創建一個新變量 request 並賦值 false。使用 false 作為判斷條件,它表示還沒有創建 XMLHttpRequest 對象。
function CreateXMLHttp(){
try{
xmlhttp = new XMLHttpRequest(); //嘗試創建 XMLHttpRequest 對象,除 IE 外的浏覽器都支持這個方法。
}
catch (e){
try{
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); //使用較新版本的 IE 創建 IE 兼容的對象(Msxml2.XMLHTTP)
}
catch (e){
try{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); //使用較老版本的 IE 創建 IE 兼容的對象(Microsoft.XMLHTTP)。
}
catch (failed){
XMLhttp = false; //如果失敗則保證 request 的值仍然為 false。
}
}
}
return XMLhttp;
}
判斷是否創建成功就很簡單了if (!XMLhttp){
//創建XMLHttpRequest 對象失敗!
}
else{
//創建成功!
}
創建好了XMLHttpRequest 對象我們再來看看這個對象的方法、屬性以及最重要的onreadystatechange事件句柄吧。
方法:
open() 說明:初始化 HTTP 請求參數,例如 URL 和 HTTP 方法,但是並不發送請求。
abort() 說明:取消當前響應,關閉連接並且結束任何未決的網絡活動。
getAllResponseHeaders() 說明:把 HTTP 響應頭部作為未解析的字符串返回。
getResponseHeader() 說明:返回指定的 HTTP 響應頭部的值。
send() 說明:發送 HTTP 請求,使用傳遞給 open() 方法的參數,以及傳遞給該方法的可選請求體。
setRequestHeader() 說明:向一個打開但未發送的請求設置或添加一個 HTTP 請求。
屬性:
readyState 說明:HTTP 請求的狀態。
responseText 說明:目前為止為服務器接收到的響應體(不包括頭部),或者如果還沒有接收到數據的話,就是空字符串。
responseXML 說明:對請求的響應,解析為 XML 並作為 Document 對象返回。
status 說明:由服務器返回的 HTTP 狀態代碼。
statusText 說明:這個屬性用名稱而不是數字指定了請求的 HTTP 的狀態代碼。
onreadystatechange 是每次 readyState 屬性改變的時候調用的事件句柄函數。
下面從發送請求並處理請求結果的過程來理解一下XMLHttpRequest 對象吧。
發送請求之前自然就是生成一個XMLHttpRequest 對象,代碼上面有了就不多寫了。
生成一個XMLHttpRequest 對象
var xmlhttp = CreateXMLHttp();
創建好XMLHttpRequest 對象了,那我們要送請求到哪個網站呢,就選擇博客園首頁的RSS吧。那怎麼設置我要請求的網站地址呢,使用open()方法。
open(method, url, async, username, passWord)
該方法有5個參數,具體什麼意思可以看這裡:http://www.w3school.com.cn/XMLdom/dom_http.ASP
我們用的就是這個了。
XMLHttp.open("get","http://www.cnblogs.com",true);
get參數表示用get方法,第二個自然就是目標地址,博客園首頁,第三個就是表示是否異步了,我們當然使用true了。具體的參數說明還都可以到http://www.w3school.com.cn上面看了。
好了,目標定好了,怎麼發送呢。用send()方法?
send(body),send()方法只有一個參數,表示DOM對象,這個DOM對象需要說明的內容很多,下次說,今天我們只要寫
xmlhttp.send();就可以了。好了,發送了,那怎麼處理返回的結果呢,這個時候就用到XMLHttpRequest 對象最重要的東西了,那就是onreadystatechange事件句柄。什麼意思呢,那就需要說明一下XMLHttpRequest 對象的readyState了,readyState有5種狀態,分別用數字的 0 到 4 來表示。
狀態 名稱 描述 0 Uninitialized 初始化狀態。XMLHttpRequest 對象已創建(未調用open()之前)或已被 abort() 方法重置。 1 Open open() 方法已調用,但是 send() 方法未調用。請求還沒有被發送。 2 Sent Send() 方法已調用,HTTP 請求已發送到 Web 服務器。未接收到響應。 3 Receiving 所有響應頭部都已經接收到。響應體開始接收但未完成。 4 Loaded HTTP 響應已經完全接收。但是需要注意的是,onreadystatechange事件句柄不同的浏覽器能處理的狀態並不一致,IE和Firefox能處理1到4,而Safari能處理2到4的狀態,Opera 能處理3、4兩中狀態。0的狀態基本沒什麼用,因為創建了XMLHttpRequest 對象後都會馬上調用open() 方法,這時候狀態就變成1了,當然除非你要判斷對象是否已經被 abort() 取消,可是這樣的情況依然很少。大部分情況下判斷是不是4(已經接受完成)這個狀態就夠了。
好了,明白了readyState有5種狀態了,那處理返回結果就是看狀態變更到不同的狀態我們做不同的處理就可以了,怎麼告訴XMLHttpRequest 對象狀態變化時讓誰來處理這個變化呢。有兩種寫法,一種是用匿名方法,另一種是指定方法,其實只是不同的寫發,作用都一樣,看下代碼:
XMLhttp.onReadyStateChange = function (){
//處理狀態變化的代碼
}
//或者
XMLhttp.onReadyStateChange = getResult;
function getResult(){
///處理狀態變化的代碼
}
順便說一下,句柄的名稱比較長,可以這樣記憶 on ReadyState Change 表示在讀取狀態改變時請求發送了,也指定處理方法了,怎麼獲取返回的內容呢,有responseText和responseXML兩個屬性可供使用,responseXML是返回對象,需要再解析,後面再說,這裡先用responseText,看看返回什麼。
alert(XMLhttp.responseText); //看看是不是返回了首頁的Html代碼啊。是你就成功了。
整個過程是:創建XMLHttpRequest 對象 -> 指定發送地址及發送方法 -> 發送請求 -> 指定處理方法並處理返回結果。但是需要注意,我們正常的思路理解是這樣的,可是onreadystatechange事件句柄指定處理方法需要在發送之前就指定好,否則無法處理狀態變化事件。
所以我們應該按照下面的流程來記憶:創建XMLHttpRequest 對象 -> 指定發送地址及發送方法 -> 指定狀態變化處理方法 -> 發送請求,請求發送後狀態變化了就會自動調用指定的處理方法。
好了,看看完成的代碼吧。
完成的代碼
var xmlhttp = false; //創建一個新變量 request 並賦值 false。使用 false 作為判斷條件,它表示還沒有創建 XMLHttpRequest 對象。
function CreateXMLHttp(){
try{
xmlhttp = new XMLHttpRequest(); //嘗試創建 XMLHttpRequest 對象,除 IE 外的浏覽器都支持這個方法。
}
catch (e){
try{
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); //使用較新版本的 IE 創建 IE 兼容的對象(Msxml2.XMLHTTP)
}
catch (e){
try{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); //使用較老版本的 IE 創建 IE 兼容的對象(Microsoft.XMLHTTP)。
}
catch (failed){
XMLhttp = false; //如果失敗則保證 request 的值仍然為 false。
}
}
}
return XMLhttp;
}
xmlhttp = CreateXMLHttp();
XMLhttp.open("get","http://www.cnblogs.com",true);
XMLhttp.onReadyStateChange = getResult;
XMLhttp.send();
function getResult(){
if(XMLhttp.readyState == 4){
alert(XMLhttp.responseText);
}
}
看似一切都OK了,可是有沒有想過,如果Html代碼在網絡傳輸過程中出錯了,或者我們指定的地址失效會怎麼樣呢。這個時候就需要用到status屬性,即由服務器返回的 HTTP 狀態代碼。 XMLhttp.status 等於200時表示傳輸過程完整沒有錯誤。具體的HTTP狀態代碼什麼意思可以到W3C組織網站上看看,地址http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.Html#sec6.1.1 。
把getResult()方法寫成下面這樣我覺的就真的OK了。
function getResult(){
if(xmlhttp.readyState == 4 && XMLhttp.status == 200){
alert(XMLhttp.responseText);
}
}
好了,一個本來挺簡單的東西,被我寫的這麼多,好象很羅嗦。不過我覺的編程對基礎內容的理解很重要,現在很多時候開發AJax的程序都使用很多JS的庫,不需要直接編寫這麼基礎的代碼。如使用著名的jQuery,但是如果我們對基礎的東西有很好的理解,那這些庫報告錯誤,或者出現問題我們可以很好很快的知道錯在哪裡,更快的做出改變使程序正常運行。