全面剖析XMLHttpRequest对象

XMLHttpRequest 对象是当今所有AJAXWeb 2.0 应用程序的技术基础。尽管软件经销商和开源社团现在都在提供各种AJAX 框架以进一步简化XMLHttpRequest 对象的使用。但是,我们仍然很有必要理解这个对象的详细工作机制。

一、 引言

  异步JavaScriptXML ( Asynchronous JavaScript and XML AJAX) 是一个专用术语,用于实现在客户端脚本与服务器之间的数据交互过程。这一技术的优点在于,它向开发者提供了一种从Web 服务器检索数据而不必把用户当前正在观察的页面回馈给服务器。与现代浏览器的通过存取浏览器DOM 结构的编程代码(JavaScript) 动态地改变被显示内容的支持相配合,AJAX 让开发者在浏览器端更新被显示的HTML 内容而不必刷新页面。换句话说,AJAX 可以使基于浏览器的应用程序更具交互性而且更类似传统型桌面应用程序。

  GoogleGmailOutlook Express 就是两个使用AJAX 技术的我们所熟悉的例子。而且,AJAX 可以用于任何客户端脚本语言中,这包括JavaScriptJscriptVBScript

AJAX 利用一个构建到所有现代浏览器内部的对象 XMLHttpRequest 来实现发送和接收HTTP 请求与响应信息。一个经由XMLHttpRequest 对象发送的HTTP 请求并不要求页面中拥有或回寄一个<form >元素。这意味着XMLHttpRequest 对象的send() 方法可以立即返回,从而让Web 页面上的其它HTML/JavaScript 继续其浏览器端处理而由服务器处理HTTP 请求并发送响应。尽管缺省情况下请求是异步进行的,但是,你可以选择发送同步请求,这将会暂停其它Web 页面的处理,直到该页面接收到服务器的响应为止。

  微软在其Internet Explorer(IE) 5 中作为一个ActiveX 对象形式引入了XMLHttpRequest 对象。其他的认识到这一对象重要性的浏览器制造商也都纷纷在他们的浏览器内实现了XMLHttpRequest 对象,但是作为一个本地JavaScript 对象而不是作为一个ActiveX 对象实现。而如今,在认识到实现这一类型的价值及安全性特征之后,微软已经在其IE 7 中把XMLHttpRequest 实现为一个窗口对象属性。幸运的是,尽管其实现细节不同( 因而也影响到调用方式) ,但是,所有的浏览器实现都具有类似的功能,并且实质上是相同方法。目前,W3C 组织正在努力进行XMLHttpRequest 对象的标准化,并且已经发行了有关该W3C 规范的一个草案。

本文将对XMLHttpRequest 对象API 进行详细讨论,并将解释其所有的属性和方法。

 

二、 XMLHttpRequest 对象的属性和事件

  XMLHttpRequest 对象暴露各种属性、方法和事件以便于脚本处理和控制HTTP 请求与响应。下面,我们将对此展开详细的讨论。

readyState 属性

XMLHttpRequest 对象把一个HTTP 请求发送到服务器时将经历若干种状态:一直等待直到请求被处理;然后,它才接收一个响应。这样以来,脚本才正确响应各种状态 XMLHttpRequest 对象暴露一个描述对象的当前状态的readyState 属性,如下所示。

XMLHttpRequest 对象的ReadyState 属性值列表。

ReadyState 取值

描述

0

" 未初始化" 状态;此时,已经创建一个XMLHttpRequest 对象,但是还没有初始化。

1

" 发送" 状态;此时,代码已经调用了XMLHttpRequest open() 方法并且XMLHttpRequest 已经准备好把一个请求发送到服务器。

2

" 发送" 状态;此时,已经通过send() 方法把一个请求发送到服务器端,但是还没有收到一个响应。

3

" 正在接收" 状态;此时,已经接收到HTTP 响应头部信息,但是消息体部分还没有完全接收结束。

4

" 已加载" 状态;此时,响应已经被完全接收。

onreadystatechange 事件

  无论readyState 值何时发生改变,XMLHttpRequest 对象都会激发一个readystatechange 事件。其中,onreadystatechange 属性接收一个EventListener 值,向该方法指示无论readyState 值何时发生改变,该对象都将激活。

 

responseText 属性

  这个responseText 属性包含客户端接收到的HTTP 响应的文本内容。当readyState 值为012 时,responseText 包含一个空字符串。当readyState 值为3( 正在接收) 时,响应中包含客户端还未完成的响应信息。当readyState4( 已加载) 时,该responseText 包含完整的响应信息。

 

responseXML 属性

  此responseXML 属性用于当接收到完整的HTTP 响应时(readyState4) 描述XML 响应;此时,ContentType 头部指定MIME( 媒体) 类型为text/xmlapplication/xml 或以+xml 结尾。如果ContentType 头部并不包含这些媒体类型之一,那么responseXML 的值为null 。无论何时,只要readyState 值不为4 ,那么该responseXML 的值也为null

  其实,这个responseXML 属性值是一个文档接口类型的对象,用来描述被分析的文档。如果文档不能被分析( 例如,如果文档不是良构的或不支持文档相应的字符编码) ,那么responseXML 的值将为null

 

status 属性

  这个status 属性描述了HTTP 状态代码。而且,仅当readyState 值为3( 正在接收中)4( 已加载) 时,这个status 属性才可用。当readyState 的值小于3 时试图存取status 的值将引发一个异常。

 

statusText 属性

  这个statusText 属性描述了HTTP 状态代码文本;并且仅当readyState 值为3( 正在接收中)4( 已加载) 才可用。当readyState 为其它值时试图存取statusText 属性将引发一个异常。

 

三、 XMLHttpRequest 对象的方法

  XMLHttpRequest 对象提供了各种方法用于初始化和处理HTTP 请求,下列将逐个展开详细讨论。

abort() 方法

  你可以使用这个abort() 方法来暂停与一个XMLHttpRequest 对象相联系的HTTP 请求,从而把该对象复位到未初始化状态。

 

open() 方法

你需要调用open(DOMString methodDOMString uriboolean asyncDOMString usernameDOMString password) 方法初始化一个XMLHttpRequest 对象。

method 参数是必须提供的用于指定你想用来发送请求的HTTP 方法(GETPOSTPUTDELETEHEAD) 。为了把数据发送到服务器,应该使用POST 方法;为了从服务器端检索数据,应该使用GET 方法。

uri 参数用于指定XMLHttpRequest 对象把请求发送到的服务器相应的URI 。借助于window.document.baseURI 属性,该uri 被解析为一个绝对的URI- 换句话说,你可以使用相对的URI 它将使用与浏览器解析相对的URI 一样的方式被解析。

async 参数指定是否请求是异步的- 缺省值为true 。为了发送一个同步请求,需要把这个参数设置为false

username password 参数对于要求认证的服务器,你可以提供可选的用户名和口令。

在调用open() 方法后,XMLHttpRequest 对象把它的readyState 属性设置为1( 打开) 并且把responseTextresponseXMLstatusstatusText 属性复位到它们的初始值。另外,它还复位请求头部。注意,如果你调用open() 方法并且此时readyState4 ,则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 headerDOMString value) 方法用来设置请求的头部信息。当readyState 值为1 时,你可以在调用open() 方法后调用这个方法;否则,你将得到一个异常。

 

getResponseHeader() 方法

  getResponseHeader(DOMString headervalue) 方法用于检索响应的头部值。仅当readyState 值是34( 换句话说,在响应头部可用以后) 时,才可以调用这个方法;否则,该方法返回一个空字符串。

 

getAllResponseHeaders() 方法

  该getAllResponseHeaders() 方法以一个字符串形式返回所有的响应头部(每一个头部占单独的一行)。如果readyState 的值不是34 ,则该方法返回null

 

四、 发送请求

AJAX 中,许多使用XMLHttpRequest 的请求都是从一个HTML 事件(例如一个调用JavaScript 函数的按钮点击(onclick) 或一个按键(onkeypress) )中被初始化的。AJAX 支持包括表单校验在内的各种应用程序。有时,在填充表单的其它内容之前要求校验一个唯一的表单域。例如要求使用一个唯一的UserID 来注册表单。如果不是使用AJAX 技术来校验这个UserID 域,那么整个表单都必须被填充和提交。如果该UserID 不是有效的,这个表单必须被重新提交。例如,一个相应于一个要求必须在服务器端进行校验的Catalog ID 的表单域可能按下列形式指定:

 

form name="validationForm" action="validateForm" method="post"

table

 <tr

tdCatalog Id:/td

  <td

   <input type="text" size="20" id="catalogId"

name="catalogId" autocomplete="off" οnkeyup="sendRequest()"

  </td

  <td ><div id="validationMessage" ></div ></td

 </tr

/table

/form

 

前面的HTML 使用validationMessage div 来显示相应于这个输入域Catalog Id 的一个校验消息。onkeyup 事件调用一个JavaScript sendRequest() 函数。这个sendRequest() 函数创建一个XMLHttpRequest 对象。创建一个XMLHttpRequest 对象的过程因浏览器实现的不同而有所区别。如果浏览器支持XMLHttpRequest 对象作为一个窗口属性( 所有普通的浏览器都是这样的,除了IE 5IE 6 之外) ,那么,代码可以调用XMLHttpRequest 的构造器。如果浏览器把XMLHttpRequest 对象实现为一个ActiveXObject 对象( 就象在IE 5IE 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 可能是一个ASPASP.NETPHP 页面或一个Web 服务- 这无关紧要,只要该页面能够返回一个响应- 指示CatalogID 值是否是有效的即可。因为你在作一个异步调用,所以你需要注册一个XMLHttpRequest 对象将调用的回调事件处理器- 当它的readyState 值改变时调用。记住,readyState 值的改变将会激发一个readystatechange 事件。你可以使用onreadystatechange 属性来注册该回调事件处理器。

 

xmlHttpReq.onreadystatechange=processRequest;

 

然后,我们需要使用send() 方法发送该请求。因为这个请求使用的是HTTP GET 方法,所以,你可以在不指定参数或使用null 参数的情况下调用send() 方法。

 

xmlHttpReq.send(null);

 

 

 五、处理请求

  在这个示例中,因为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(" catalogIdvalid/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 对象的responseXMLresponseText 属性来检索HTTP 响应。如上面所解释的,仅当在响应的媒体类型是text/xmlapplication/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";

}

 

六、 小结

  上面就是XMLHttpRequest 对象使用的所有细节实现。通过不必把Web 页面寄送到服务器而实现数据传送,XMLHttpRequest 对象为客户端与服务器之间提供了一种动态的交互能力。你可以使用JavaScript 启动一个请求并处理相应的返回值,然后使用浏览器的DOM 方法更新页面中的数据。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值