1.3 XMLHttpRequest的誕生
阻止頁面刷新的方法其實很簡單,頁面刷新是為了要將數據送回服務器端,然后由服務器端取得更新后的頁面來顯示,那么如果能在不刷新頁面的情況下,將數據送往服務器端,不就能解決頁面刷新的問題了嗎?只是在瀏覽器的原始設計概念中,要將數據送到服務器端就得背負刷新頁面的原罪,除非改變原始設計概念,否則問題就是無解!很幸運地,由微軟推出的Internet Explorer,簡稱IE的瀏覽器打破了這個僵局,在XML盛行初期,修改了一部分瀏覽器的設計概念,允許設計師在JavaScript中創建一個ActiveX對象:XMLHttpRequest,利用這個對象,設計師可以用JavaScript將數據直接送到服務器端而不引發頁面刷新的操作,只是在當時這個功能并不算公認的瀏覽器標準,在眾多瀏覽器不支持的情況下,XMLHttpRequest 也只能靜靜躺在實驗室中。直到今日,除IE外的其他主流瀏覽器如Netscapce、Mozilla都已支持同樣的功能,讓 XMLHttpRequest 在一瞬間成了標準之外的熱門技術,以此對象為核心的新名詞AJAX“全名是Asynchronous JavaScript And XML”也就誕生了,Asynchronous 的語義來源于 XMLHttpRequest 所采取的異步行為模式,使用XMLHttpRequest 發送數據時,必須指定一個接收返回數據的函數,送出數據后,客戶端不必停下來等候數據的返回,XMLHttpRequest 取得返回數據后會調用指定的函數將數據傳過去,圖1-2是其流程圖。
圖1-2 在創建 XMLHttpRequest 對象時,指定processRequest函數為收取返回數據的函數,在XMLHttpRequest的send函數被調用后,XMLHttpRequest即發送要求,需特別注意的一點是,send函數不會像傳統函數調用般等待要求被處理后而收取返回值,而是直接返回,繼續運行下面的JavaScript程序,或將主導權還給瀏覽器,此行為模式正是AJAX中的Asynchronous 語義來源。AJAX中的J代表的是JavaScript,雖然IE可以用VBScript來使用XMLHttpRequest對象,但是JavaScript才是諸多瀏覽器所支持的標準語言,因此AJAX中的J代表的是啟動XMLHttpRequest對象時所使用的語言。AJAX中的第二個A代表的是“And”,

圖1-2
最后的“X”代表的是使用 XMLHttpRequest 對象時所使用的數據協議,也就是XML文件格式。好了,了解 XMLHttpRequest 的歷史后,現在就以一個實例(如程序1-1)來看看 XMLHttp-Request究竟有何神妙之處,為什么可以引發第二次的網頁革命。
程序1-1
Samples\1\XMLHttpRequestDemo\Default.aspx <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> <script language=javascript> var req; function loadXMLDoc(url) { req = false; //視不同瀏覽器,使用不同的方式創建XMLHttpRequest對象 if(window.XMLHttpRequest && !(window.ActiveXObject)) //FireFox { try { req = new XMLHttpRequest(); } catch(e) { req = false; } } else if(window.ActiveXObject) //IE { try { req = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { req = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { req = false; } } } if(req) { //指定要求處理后,收取返回值的函數 req.onreadystatechange = processReqChange; //開啟通信管道 req.open("GET", url, true); //use get method //發送要求,請注意,send函數不會等待返回值,而是直接返回。 req.send(""); } } function processReqChange() { if (req.readyState == 4) //readyState = 4 代表要求已被處理 { if (req.status == 200) //200代表服務器端正常的處理要求 //responseXML中包含服務器返回的XML數據。 document.getElementById("Button1").value = req.responseXML.getElementsByTagName('Result')[0].getAttribute('Val'); else alert("There was a problem retrieving the XML data:\n"+req.statusText); } } function callBack() { loadXMLDoc('<%=Request.Url%>?CallBack=true'); } </script> <asp:Button ID="Button1" UseSubmitBehavior=false runat="server" Text="Button" OnClientClick="callBack(); return false;"/> <br /> <asp:Label ID="Label1" runat="server"></asp:Label> </div> </form> </body> </html> Samples\1\XMLHttpRequestDemo\Default.aspx.cs using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (Request.QueryString["CallBack"] != null) { Response.ContentType = "text/xml"; Response.Write( "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Result Val='TEST'/>"); Response.End(); } } } 圖1-3為此程序運行后,點擊按鈕后的結果。

圖1-3
請注意,在運行 XMLHttpRequest 期間不會引發任何的頁面刷新操作,就是這個設計使得XMLHttpRequest在誕生多年后,一躍成為引發第二波網頁革命的關鍵。