JavaScript XMLHttpRequest 对象全面剖析
本文详细解析 JavaScript 中的 XMLHttpRequest 对象,涵盖其属性(如 readyState、status)、方法(open、send、abort)及事件处理机制。通过具体代码示例,展示如何创建对象、发送同步或异步 HTTP 请求,并处理服务器响应,实现无需刷新页面的动态数据交互。
引言
异步 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 进行详细讨论,并将解释其所有的属性和方法。
二、 XMLHttpRequest 对象的属性和事件
XMLHttpRequest 对象的属性和事件
XMLHttpRequest 对象暴露各种属性、方法和事件以便于脚本处理和控制 HTTP 请求与响应。下面,我们将对此展开详细的讨论。
readyState 属性
当 XMLHttpRequest 对象把一个 HTTP 请求发送到服务器时将经历若干种状态:一直等待直到请求被处理;然后,它才接收一个响应。这样以来,脚本才正确响应各种状态 -XMLHttpRequest 对象暴露一个描述对象的当前状态的 readyState 属性,如表格 1 所示。
表格 1.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 值为 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 属性将引发一个异常。
XMLHttpRequest 对象的方法
三、 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。
发送请求
四、 发送请求 在 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); |
处理请求
五、 处理请求 在这个示例中,因为 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"; } |
六、 小结
小结
上面就是 XMLHttpRequest 对象使用的所有细节实现。通过不必把 Web 页面寄送到服务器而实现数据传送,XMLHttpRequest 对象为客户端与服务器之间提供了一种动态的交互能力。你可以使用 JavaScript 启动一个请求并处理相应的返回值,然后使用浏览器的 DOM 方法更新页面中的数据。
JavaScript怎么遍历对象的Symbol键和不可枚举属性
2026-11-05 13:13:39
封装一个健壮的JS字符串判空工具函数
2026-11-05 12:16:14
JavaScript合并数组的三种常用方法:concat、扩展运算符与push
2026-11-05 11:22:29
JavaScript立即执行函数(IIFE)是什么及基本语法
2026-11-05 10:51:19
JS对象数组转字符串为什么推荐用JSON.stringify()
2026-11-05 09:40:31
