
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在诞生多年后,一跃成为引发第二波网页革命的关键。