轉載:http://www.jb51.net/article/23175.htmjavascript
1、 引言
異步JavaScript與XML(AJAX)是一個專用術語,用於實如今客戶端腳本與服務器之間的數據交互過程。這一技術的優勢在於,它向開發者提供了一種從Web服務器檢索數據而沒必要把用戶當前正在觀察的頁面回饋給服務器。與現代瀏覽器的經過存取瀏覽器DOM結構的編程代碼(JavaScript)動態地改變被顯示內容的支持相配合,AJAX讓開發者在瀏覽器端更新被顯示的HTML內容而沒必要刷新頁面。換句話說,AJAX可使基於瀏覽器的應用程序更具交互性並且更相似傳統型桌面應用程序。
Google的Gmail和Outlook Express就是兩個使用AJAX技術的咱們所熟悉的例子。並且,AJAX能夠用於任何客戶端腳本語言中,這包括JavaScript,Jscript和VBScript。
AJAX利用一個構建到全部現代瀏覽器內部的對象-XMLHttpRequest-來實現發送和接收HTTP請求與響應信息。一個經由XMLHttpRequest對象發送的HTTP請求並不要求頁面中擁有或回寄一個<form>元素。AJAX中的"A"表明了"異步",這意味着XMLHttpRequest對象的send()方法能夠當即返回,從而讓Web頁面上的其它HTML/JavaScript繼續其瀏覽器端處理而由服務器處理HTTP請求併發送響應。儘管缺省狀況下請求是異步進行的,可是,你能夠選擇發送同步請求,這將會暫停其它Web頁面的處理,直到該頁面接收到服務器的響應爲止。
微軟在其Internet Explorer(IE) 5中做爲一個ActiveX對象形式引入了XMLHttpRequest對象。其餘的認識到這一對象重要性的瀏覽器製造商也都紛紛在他們的瀏覽器內實現了XMLHttpRequest對象,可是做爲一個本地JavaScript對象而不是做爲一個ActiveX對象實現。而現在,在認識到實現這一類型的價值及安全性特徵以後,微軟已經在其IE 7中把XMLHttpRequest實現爲一個窗口對象屬性。幸運的是,儘管其實現(於是也影響到調用方式)細節不一樣,可是,全部的瀏覽器實現都具備相似的功能,而且實質上是相同方法。目前,W3C組織正在努力進行XMLHttpRequest對象的標準化,而且已經發行了有關該W3C規範的一個草案。
本文將對XMLHttpRequest對象API進行詳細討論,並將解釋其全部的屬性和方法。
2、 XMLHttpRequest對象的屬性和事件
XMLHttpRequest對象暴露各類屬性、方法和事件以便於腳本處理和控制HTTP請求與響應。下面,咱們將對此展開詳細的討論。
readyState屬性
當XMLHttpRequest對象把一個HTTP請求發送到服務器時將經歷若干種狀態:一直等待直到請求被處理;而後,它才接收一個響應。這樣以來,腳本才正確響應各類狀態-XMLHttpRequest對象暴露一個描述對象的當前狀態的readyState屬性,如表格1所示。
表格1.XMLHttpRequest對象的ReadyState屬性值列表。
java
ReadyState取值 | 描述 |
0
|
描述一種"未初始化"狀態;此時,已經建立一個XMLHttpRequest對象,可是尚未初始化。 |
1
|
描述一種"發送"狀態;此時,代碼已經調用了XMLHttpRequest open()方法而且XMLHttpRequest已經準備好把一個請求發送到服務器。 |
2
|
描述一種"發送"狀態;此時,已經經過send()方法把一個請求發送到服務器端,可是尚未收到一個響應。 |
3
|
描述一種"正在接收"狀態;此時,已經接收到HTTP響應頭部信息,可是消息體部分尚未徹底接收結束。 |
4
|
描述一種"已加載"狀態;此時,響應已經被徹底接收。 |
onreadystatechange事件
不管readyState值什麼時候發生改變,XMLHttpRequest對象都會激發一個readystatechange事件。其中,onreadystatechange屬性接收一個EventListener值-向該方法指示不管readyState值什麼時候發生改變,該對象都將激活。
responseText屬性
這個responseText屬性包含客戶端接收到的HTTP響應的文本內容。當readyState值爲0、1或2時,responseText包含一個空字符串。當readyState值爲3(正在接收)時,響應中包含客戶端還未完成的響應信息。當readyState爲4(已加載)時,該responseText包含完整的響應信息。
responseXML屬性
此responseXML屬性用於當接收到完整的HTTP響應時(readyState爲4)描述XML響應;此時,Content-Type頭部指定MIME(媒體)類型爲text/xml,application/xml或以+xml結尾。若是Content-Type頭部並不包含這些媒體類型之一,那麼responseXML的值爲null。不管什麼時候,只要readyState值不爲4,那麼該responseXML的值也爲null。
其實,這個responseXML屬性值是一個文檔接口類型的對象,用來描述被分析的文檔。若是文檔不能被分析(例如,若是文檔不是良構的或不支持文檔相應的字符編碼),那麼responseXML的值將爲null。
status屬性
這個status屬性描述了HTTP狀態代碼,並且其類型爲short。並且,僅當readyState值爲3(正在接收中)或4(已加載)時,這個status屬性纔可用。當readyState的值小於3時試圖存取status的值將引起一個異常。
statusText屬性
這個statusText屬性描述了HTTP狀態代碼文本;而且僅當readyState值爲3或4纔可用。當readyState爲其它值時試圖存取statusText屬性將引起一個異常。node
3、 XMLHttpRequest對象的方法
XMLHttpRequest對象提供了各類方法用於初始化和處理HTTP請求,下列將逐個展開詳細討論。
abort()方法
你可使用這個abort()方法來暫停與一個XMLHttpRequest對象相聯繫的HTTP請求,從而把該對象復位到未初始化狀態。
open()方法
你須要調用open(DOMString method,DOMString uri,boolean async,DOMString username,DOMString password)方法初始化一個XMLHttpRequest對象。其中,method參數是必須提供的-用於指定你想用來發送請求的HTTP方法(GET,POST,PUT,DELETE或HEAD)。爲了把數據發送到服務器,應該使用POST方法;爲了從服務器端檢索數據,應該使用GET方法。另外,uri參數用於指定XMLHttpRequest對象把請求發送到的服務器相應的URI。藉助於window.document.baseURI屬性,該uri被解析爲一個絕對的URI-換句話說,你可使用相對的URI-它將使用與瀏覽器解析相對的URI同樣的方式被解析。async參數指定是否請求是異步的-缺省值爲true。爲了發送一個同步請求,須要把這個參數設置爲false。對於要求認證的服務器,你能夠提供可選的用戶名和口令參數。在調用open()方法後,XMLHttpRequest對象把它的readyState屬性設置爲1(打開)而且把responseText、responseXML、status和statusText屬性復位到它們的初始值。另外,它還復位請求頭部。注意,若是你調用open()方法而且此時readyState爲4,則XMLHttpRequest對象將復位這些值。
send()方法
在經過調用open()方法準備好一個請求以後,你須要把該請求發送到服務器。僅當readyState值爲1時,你才能夠調用send()方法;不然的話,XMLHttpRequest對象將引起一個異常。該請求被使用提供給open()方法的參數發送到服務器。當async參數爲true時,send()方法當即返回,從而容許其它客戶端腳本處理繼續。在調用send()方法後,XMLHttpRequest對象把readyState的值設置爲2(發送)。當服務器響應時,在接收消息體以前,若是存在任何消息體的話,XMLHttpRequest對象將把readyState設置爲3(正在接收中)。當請求完成加載時,它把readyState設置爲4(已加載)。對於一個HEAD類型的請求,它將在把readyState值設置爲3後再當即把它設置爲4。
send()方法使用一個可選的參數-該參數能夠包含可變類型的數據。典型地,你使用它並經過POST方法把數據發送到服務器。另外,你能夠顯式地使用null參數調用send()方法,這與不用參數調用它同樣。對於大多數其它的數據類型,在調用send()方法以前,應該使用setRequestHeader()方法(見後面的解釋)先設置Content-Type頭部。若是在send(data)方法中的data參數的類型爲DOMString,那麼,數據將被編碼爲UTF-8。若是數據是Document類型,那麼將使用由data.xmlEncoding指定的編碼串行化該數據。
setRequestHeader()方法
該setRequestHeader(DOMString header,DOMString value)方法用來設置請求的頭部信息。當readyState值爲1時,你能夠在調用open()方法後調用這個方法;不然,你將獲得一個異常。
getResponseHeader()方法
getResponseHeader(DOMString header,value)方法用於檢索響應的頭部值。僅當readyState值是3或4(換句話說,在響應頭部可用之後)時,才能夠調用這個方法;不然,該方法返回一個空字符串。
getAllResponseHeaders()方法
該getAllResponseHeaders()方法以一個字符串形式返回全部的響應頭部(每個頭部佔單獨的一行)。若是readyState的值不是3或4,則該方法返回null。數據庫
4、 發送請求
在AJAX中,許多使用XMLHttpRequest的請求都是從一個HTML事件(例如一個調用JavaScript函數的按鈕點擊(onclick)或一個按鍵(onkeypress))中被初始化的。AJAX支持包括表單校驗在內的各類應用程序。有時,在填充表單的其它內容以前要求校驗一個惟一的表單域。例如要求使用一個惟一的UserID來註冊表單。若是不是使用AJAX技術來校驗這個UserID域,那麼整個表單都必須被填充和提交。若是該UserID不是有效的,這個表單必須被從新提交。例如,一個相應於一個要求必須在服務器端進行校驗的Catalog ID的表單域可能按下列形式指定:
編程
<form name="validationForm" action="validateForm" method="post"> <table> <tr><td>Catalog Id:</td> <td> <input type="text" size="20" id="catalogId" name="catalogId" autocomplete="off" onkeyup="sendRequest()"> </td> <td><div id="validationMessage"></div></td> </tr> </table></form> |
前面的HTML使用validationMessage div來顯示相應於這個輸入域Catalog Id的一個校驗消息。onkeyup事件調用一個JavaScript sendRequest()函數。這個sendRequest()函數建立一個XMLHttpRequest對象。建立一個XMLHttpRequest對象的過程因瀏覽器實現的不一樣而有所區別。若是瀏覽器支持XMLHttpRequest對象做爲一個窗口屬性(全部普通的瀏覽器都是這樣的,除了IE 5和IE 6以外),那麼,代碼能夠調用XMLHttpRequest的構造器。若是瀏覽器把XMLHttpRequest對象實現爲一個ActiveXObject對象(就象在IE 5和IE 6中同樣),那麼,代碼可使用ActiveXObject的構造器。下面的函數將調用一個init()函數,它負責檢查並決定要使用的適當的建立方法-在建立和返回對象以前。
瀏覽器
<script type="text/javascript"> function sendRequest(){ var xmlHttpReq=init(); function init(){ if (window.XMLHttpRequest) { return new XMLHttpRequest(); } else if (window.ActiveXObject) { return new ActiveXObject("Microsoft.XMLHTTP"); } } </script> |
接下來,你須要使用Open()方法初始化XMLHttpRequest對象-指定HTTP方法和要使用的服務器URL。
緩存
var catalogId=encodeURIComponent(document.getElementById("catalogId").value); xmlHttpReq.open("GET", "validateForm?catalogId=" + catalogId, true); |
默認狀況下,使用XMLHttpRequest發送的HTTP請求是異步進行的,可是你能夠顯式地把async參數設置爲true,如上面所展現的。
在這種狀況下,對URL validateForm的調用將激活服務器端的一個servlet,可是你應該可以注意到服務器端技術不是根本性的;實際上,該URL多是一個ASP,ASP.NET或PHP頁面或一個Web服務-這可有可無,只要該頁面可以返回一個響應-指示CatalogID值是不是有效的-便可。由於你在做一個異步調用,因此你須要註冊一個XMLHttpRequest對象將調用的回調事件處理器-當它的readyState值改變時調用。記住,readyState值的改變將會激發一個readystatechange事件。你可使用onreadystatechange屬性來註冊該回調事件處理器。
安全
xmlHttpReq.onreadystatechange=processRequest; |
而後,咱們須要使用send()方法發送該請求。由於這個請求使用的是HTTP GET方法,因此,你能夠在不指定參數或使用null參數的狀況下調用send()方法。
服務器
xmlHttpReq.send(null); |
5、 處理請求
在這個示例中,由於HTTP方法是GET,因此在服務器端的接收servlet將調用一個doGet()方法,該方法將檢索在URL中指定的catalogId參數值,而且從一個數據庫中檢查它的有效性。
本文示例中的這個servlet須要構造一個發送到客戶端的響應;並且,這個示例返回的是XML類型,所以,它把響應的HTTP內容類型設置爲text/xml而且把Cache-Control頭部設置爲no-cache。設置Cache-Control頭部能夠阻止瀏覽器簡單地從緩存中重載頁面。
併發
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ... ... response.setContentType("text/xml"); response.setHeader("Cache-Control", "no-cache"); } |
來自於服務器端的響應是一個XML DOM對象,此對象將建立一個XML字符串-其中包含要在客戶端進行處理的指令。另外,該XML字符串必須有一個根元素。
out.println("<catalogId>valid</catalogId>"); |
【注意】XMLHttpRequest對象的設計目的是爲了處理由普通文本或XML組成的響應;可是,一個響應也多是另一種類型,若是用戶代理(UA)支持這種內容類型的話。
當請求狀態改變時,XMLHttpRequest對象調用使用onreadystatechange註冊的事件處理器。所以,在處理該響應以前,你的事件處理器應該首先檢查readyState的值和HTTP狀態。當請求完成加載(readyState值爲4)而且響應已經完成(HTTP狀態爲"OK")時,你就能夠調用一個JavaScript函數來處理該響應內容。下列腳本負責在響應完成時檢查相應的值並調用一個processResponse()方法。
function processRequest(){ if(xmlHttpReq.readyState==4){ if(xmlHttpReq.status==200){ processResponse(); } } } |
該processResponse()方法使用XMLHttpRequest對象的responseXML和responseText屬性來檢索HTTP響應。如上面所解釋的,僅當在響應的媒體類型是text/xml,application/xml或以+xml結尾時,這個responseXML纔可用。這個responseText屬性將以普通文本形式返回響應。對於一個XML響應,你將按以下方式檢索內容:
var msg=xmlHttpReq.responseXML; |
藉助於存儲在msg變量中的XML,你可使用DOM方法getElementsByTagName()來檢索該元素的值:
var catalogId=msg.getElementsByTagName("catalogId")[0].firstChild.nodeValue; |
最後,經過更新Web頁面的validationMessage div中的HTML內容並藉助於innerHTML屬性,你能夠測試該元素值以建立一個要顯示的消息:
if(catalogId=="valid"){ var validationMessage = document.getElementById("validationMessage"); validationMessage.innerHTML = "Catalog Id is Valid"; } else { var validationMessage = document.getElementById("validationMessage"); validationMessage.innerHTML = "Catalog Id is not Valid"; } |
6、 小結 上面就是XMLHttpRequest對象使用的全部細節實現。經過沒必要把Web頁面寄送到服務器而實現數據傳送,XMLHttpRequest對象爲客戶端與服務器之間提供了一種動態的交互能力。你可使用JavaScript啓動一個請求並處理相應的返回值,而後使用瀏覽器的DOM方法更新頁面中的數據。