`
icybamboo
  • 浏览: 39193 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

XMLHTTP.readyState的五种状态(转)

阅读更多

对于很多 Web 开发人员来说,只需要生成简单的请求并接收简单的响应即可;但是对于希望掌握 Ajax 的开发人员来说,必须要全面理解 HTTP 状态代码、就绪状态和 XMLHttpRequest 对象。在本文中,Brett McLaughlin 将向您介绍各种状态代码,并展示浏览器如何对其进行处理,本文还给出了在 Ajax 中使用的比较少见的 HTTP 请求。

在本系列的 上篇文章 中,我们将详细介绍 XMLHttpRequest 对象,它是 Ajax 应用程序的中心,负责处理服务器端应用程序和脚本的请求,并处理从服务器端组件返回的数据。由于所有的 Ajax 应用程序都要使用 XMLHttpRequest 对象,因此您可能会希望熟悉这个对象,从而能够让 Ajax 执行得更好。
在本文中,我将在上一篇文章的基础上重点介绍这个请求对象的 3 个关键部分的内容:

HTTP 就绪状态
HTTP 状态代码
可以生成的请求类型
这 三部分内容都是在构造一个请求时所要考虑的因素;但是介绍这些主题的内容太少了。然而,如果您不仅仅是想了解 Ajax 编程的常识,而是希望了解更多内容,就需要熟悉就绪状态、状态代码和请求本身的内容。当应用程序出现问题时 —— 这种问题总是存在 —— 那么如果能够正确理解就绪状态、如何生成一个 HEAD 请求或者 400 的状态代码的确切含义,就可以在 5 分钟内调试出问题,而不是在各种挫折和困惑中度过 5 个小时。
XMLHttpRequest 或 XMLHttp:换名玫瑰
Microsoft™ 和 Internet Explorer 使用了一个名为 XMLHttp 的对象,而不是 XMLHttpRequest 对象,而 Mozilla、Opera、Safari 和 大部分非 Microsoft 浏览器都使用的是后者。为了简单性起见,我将这两个对象都简单地称为 XMLHttpRequest。这既符合 我们在 Web 上看到的情况,又符合 Microsoft 在 Internet Explorer 7.0 中使用 XMLHttpRequest 作为请求对象的意图。(有关这个问题的更多内容,请参见 第 2 部分。)
下 面让我们首先来看一下 HTTP 就绪状态。
深入了解 HTTP 就绪状态
您应该还记得在上一篇文章中 XMLHttpRequest 对象有一个名为 readyState 的属性。这个属性确保服务器已经完成了一个请求,通常会使用一个回调函数从服务器中读出数据来更新 Web 表单或页面的内容。清单 1 给出了一个简单的例子(这也是本系列的上一篇文章中的一个例子 —— 请参见 参考资料)。

清单 1. 在回调函数中处理服务器的响应

function updatePage() {
if (request.readyState == 4) {
if (request.status == 200) {
var response = request.responseText.split("|");
document.getElementById("order").value = response[0];
document.getElementById("address").innerHTML =
response[1].replace(/\n/g, "<br />");
} else
alert("status is " + request.status);
}
}


这 显然是就绪状态最常见(也是最简单)的用法。正如您从数字 "4" 中可以看出的一样,还有其他几个就绪状态(您在上一篇文章中也看到过这个清单 —— 请参见 参考资料):

0: 请求未初始化(还没有调用 open())。
1:请求已经建立,但是还没有发送(还没有调用 send())。
2:请求已发送, 正在处理中(通常现在可以从响应中获取内容头)。
3:请求在处理中;通常响应中已有部分数据可用了,但是服 务器还没有完成响应的生成。
4:响应已完成;您可以获取并使用服务器的响应了。
如 果您希望不仅仅是了解 Ajax 编程的基本知识,那么就不但需要知道这些状态,了解这些状态是何时出现的,以及如何来使用这些状态。首先,您需要学习在每种就绪状态下可能碰到的是哪种请 求状态。不幸的是,这一点并不直观,而且会涉及几种特殊的情况。
隐秘就绪状态
第一种就绪状态的特点是 readyState 属性为 0(readyState == 0),表示 未初始化状态。一旦对请求对象调用 open() 之后,这个属性就被设置为 1。由于您通常都是在一对请求进行初始化之后就立即调用 open(),因此很少会看到 readyState == 0 的状态。另外,未初始化的就绪状态在实际的应用程序中是没有真正的用处的。
不过为了满足我们的兴趣,请参见 清单 2 的内容,其中显示了如何在 readyState 被设置为 0 时来获取这种就绪状态。

清单 2. 获取 0 就绪状态


   function getSalesData() {
// Create a request object
createRequest();  
alert("Ready state is: " + request.readyState);

// Setup (initialize) the request
var url = "/boards/servlet/UpdateBoardSales";
request.open("GET", url, true);
request.onreadystatechange = updatePage;
request.send(null);
}


在这个简单的例子中,getSalesData() 是 Web 页面调用来启动请求(例如点击一个按钮时)所使用的函数。注意您必须在调用 open()之前 来查看就绪状态。图 1 给出了运行这个应用程序的结果。

图 1. 就绪状态 0

当 0 等于 4 时
在多个 JavaScript 函数都使用相同的请求对象时,您需要检查就绪状态 0 来确保这个请求对象没有正在使用,这种机制会产生问题。由于 readyState == 4 表示一个已完成的请求,因此您经常会发现那些目前没在使用的处于就绪状态的请求对象仍然被设置成了 4 —— 这是因为从服务器返回来的数据已经使用过了,但是从它们被设置为就绪状态之后就没有进行任何变化。有一个函数 abort() 会重新设置请求对象,但是这个函数却不是真正为了这个目的而使用的。如果您 必须 使用多个函数,最好是为每个函数都创建并使用一个函数,而不是在多个函数之间共享相同的对象。
显然,这并不能为您带来多少好处;需要确保 尚未 调用 open() 函数的情况很少。在大部分 Ajax 编程的真实情况中,这种就绪状态的唯一用法就是使用相同的 XMLHttpRequest 对象在多个函数之间生成多个请求。在这种(不常见的)情况中,您可能会在生成新请求之前希望确保请求对象是处于未初始化状态(readyState == 0)。这实际 上是要确保另外一个函数没有同时使用这个对象。
查看正在处理的请求的就绪状态
除了 0 就绪状态之外,请求对象还需要依次经历典型的请求和响应的其他几种就绪状态,最后才以就绪状态 4 的形式结束。这就是为什么您在大部分回调函数中都可以看到 if (request.readyState == 4) 这行代码;它确保服务器已经完成对请求的处理,现在可以安全地更新 Web 页面或根据从服务器返回来的数据来进行操作了。
要查看这种状态发生的 过程非常简单。如果就绪状态为 4,我们不仅要运行回调函数中的代码,而且还要在每次调用回调函数时都输出就绪状态。 清单 3 给出了一个实现这种功能的例子。

清单 3. 查看就绪状态


   function updatePage() {
// Output the current ready state
alert("updatePage() called with ready state of " + request.readyState);
}


如果您不确定如何运行这个函数,就需要创建一个函数,然后在 Web 页面中调用这个函数,并让它向服务器端的组件发送一个请求(例如 清单 2 给出的函数,或本系列文章的第 1 部分和第 2 部分中给出的例子)。确保在建立请求时,将回调函数设置为 updatePage();要实现这种设 置,可以将请求对象的 onreadystatechange 属性设置为 updatePage()
这 段代码就是 onreadystatechange 意义的一个确切展示 —— 每次请求的就绪状态发生变化时,就调用 updatePage(),然后我们就可以看到一个警告了。图 2 给出了一个调用这个函数的例子,其中就绪状态为 1。

图 2. 就绪状态 1


您可以自己尝试运行这段代码。将其放入 Web 页面中,然后激活事件处理程序(单击按钮,在域之间按 tab 键切换焦点,或者使用设置的任何方法来触发请求)。这个回调函数会运行多次 —— 每次就绪状态都会改变 —— 您可以看到每个就绪状态的警告。这是跟踪请求所经历的各个阶段的最好方法。
浏览器的不一致性
在 对这个过程有一个基本的了解之后,请试着从几个不同的浏览器中访问您的页面。您应该会注意到各个浏览器如何处理这些就绪状态并不一致。例如,在 Firefox 1.5 中,您会看到以下就绪状态:

1
2
3
4
这 并不奇怪,因为每个请求状态都在这里表示出来了。然而,如果您使用 Safari 来访问相同的应用程序,就应该看到 —— 或者看不到 —— 一些有趣的事情。下面是在 Safari 2.0.1 中看到的状态:

2
3
4
Safari 实际上把第一个就绪状态给丢弃了,也并没有什么明显的原因说明为什么要这样做;不过这就是 Safari 的工作方式。这还说明了一个重要的问题:尽管在使用服务器上的数据之前确保请求的状态为 4 是一个好主意,但是依赖于每个过渡期就绪状态编写的代码的确会在不同的浏览器上得到不同的结果。
例如,在使用 Opera 8.5 时,所显示的就绪状态情况就更加糟糕了:

3
4
最后,Internet Explorer 会显示如下状态:

1
2
3
4
如果您碰到请 求方面的问题,这就是用来发现问题的 首要之处。最好的方式是在 Internet Explorer 和 Firefox 都进行一下测试 —— 您会看到所有这 4 种状态,并可以检查请求的每个状态所处的情况。
接下来我们再来看一下响应端的情况。
显微镜下的响应数据
一 旦我们理解在请求过程中发生的各个就绪状态之后,接下来就可以来看一下 XMLHttpRequest 对象的另外一个方面了 —— responseText 属性。回想一下在上一篇文章中我们介绍过的内容,就可以知道这个属性用来从服务器上获取数据。一旦服务器完成对请求的处理之后,就可以将响应请求数据所需 要的任何数据放到请求的 responseText 中了。然后回调函数就可以使用这些数据,如 清单 1清单 4 所示。

清单 4. 使用服务器上返回的响应

   function updatePage() {
if (request.readyState == 4) {
var newTotal = request.responseText;
var totalSoldEl = document.getElementById("total-sold");
var netProfitEl = document.getElementById("net-profit");
replaceText(totalSoldEl, newTotal);

/* 图 out the new net profit */
var boardCostEl = document.getElementById("board-cost");
var boardCost = getText(boardCostEl);
var manCostEl = document.getElementById("man-cost");
var manCost = getText(manCostEl);
var profitPerBoard = boardCost - manCost;
var netProfit = profitPerBoard * newTotal;

/* Update the net profit on the sales form */
netProfit = Math.round(netProfit * 100) / 100;
replaceText(netProfitEl, netProfit);
}


清单 1 相当简单;清单 4 稍微有点复杂,但是它们在开始时都要检查就绪状态,并获取 responseText 属性的值。
查看请求的响应文本
与 就绪状态类似,responseText 属性的值在整个请求的生命周期中也会发生变化。要查看这种变化,请使用如 清单 5 所示的代码来测试请求的响应文本,以及它们的就绪状态。

清单 5. 测试 responseText 属性


   function updatePage() {
// Output the current ready state
alert("updatePage() called with ready state of " + request.readyState +
" and a response text of '" + request.responseText + "'");
}


现在在浏览器中打开 Web 应用程序,并激活您的请求。要更好地看到这段代码的效果,请使用 Firefox 或 Internet Explorer,因为这两个浏览器都可以报告出请求过程中所有可能的就绪状态。例如在就绪状态 2 中,就没有定义 responseText (请参见 图 3); 如果 JavaScript 控制台也已经打开了,您就会看到一个错误。

图 3. 就绪状态为 2 的响应文本


不过在就绪状态 3 中,服务器已经在 responseText 属性中放上了一个值,至少在这个例子中是这样(请参见 图 4)。

图 4. 就绪状态为 3 的响应文本


您会看到就绪状态为 3 的响应在每个脚本、每个服务器甚至每个浏览器上都是不一样的。不过,这在调试应用程序中依然是非常有用的。
获取安全数据
所 有的文档和规范都强调,只有在就绪状态为 4 时数据才可以安全使用。相信我,当就绪状态为 3 时,您很少能找到无法从 responseText 属性获取数据的情况。然而,在应用程序中将自己的逻辑依赖于就绪状态 3 可不是什么好主意 —— 一旦您编写了依赖于就绪状态 3 的完整数据的的代码,几乎就要自己来负责当时的数据不完整问题了。
比较好的做法是向用户提供一些反馈,说明在处于就绪状态 3 时,很快就会有响应了。尽管使用 alert() 之类的函数显然不是什么好主意 —— 使用 Ajax 然后使用一个警告对话框来阻塞用户显然是错误的 —— 不过您可以在就绪状态发生变化时更新表单或页面中的域。例如,对于就绪状态 1 来说要将进度指示器的宽度设置为 25%,对于就绪状态 2 来说要将进度指示器的宽度设置为 50%,对于就绪状态 3 来说要将进度指示器的宽度设置为 75%,当就绪状态为 4 时将进度指示器的宽度设置为 100%(完成)。
当然,正如您已经看到的一样,这种方法非常聪明,但它是依赖于浏览器的。在 Opera 上,您永远都不会看到前两个就绪状态,而在 Safari 上则没有第一个(1)。由于这个原因,我将这段代码留作练习,而没有在本文中包括进来。
现 在应该来看一下状态代码了。
分享到:
评论

相关推荐

    WEB开发 之 AJAX - 向服务器发送请求.docx

    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { document.getElementById("myDiv").innerHTML = xmlhttp.responseText; } } ``` 使用AJAX技术可以实现客户端和服务器之间的异步通信,提高Web应用程序...

    XMLHttpRequest

    1.readyState属性 readyState:只读属性。 作用:通过读取该属性,从而知道XMLHttpRequest 目前进行到了哪一步 取值: 状态码 名称 描述 0 未初始化 默认状态,XMLHttpRequest刚刚被创建 1 打开 调用了对象的...

    AJAX的使用方法详解

    AJAX作为异步传输,局部刷新非常方便,用处很广! 首先,对于AJAX的使用有4步: 1.创建AJAX对象 var xmlHttp = new ... if (xmlHttp.readyState==4 && xmlHttp.status==200) { } } 4.发送请求 xmlHttp.send(null);

    XMLHttpRequest处理xml格式的返回数据(示例代码)

    接收响应数据 //判断对象的状态是交互完成 if (xmlhttp.readyState == 4) { //判断http的交互是否成功 if (xmlhttp.status == 200) { //使用responseXML的方式来接收XML数据对象的DOM对象 var domObj = ...

    ajax readyState的五种状态详解

    在《Pragmatic Ajax A Web 2.0 Primer 》中对readyStae状态的介绍,摘译如下: 0: (Uninitialized) the send( ) method has not yet been invoked. 1: (Loading) the send( ) method has been invoked, request in ...

    Ajax实现客户端验证(连接数据库检查用户名&ID是否唯一)终版.pdf

    readyState 属性有五个状态:0(未初始化)、1(正在加载)、2(加载完毕)、3(交互中)和 4(完成)。我们需要等待 readyState 等于 4,才可以进行下一步的操作。 最后,我们需要使用 JavaScript 来处理服务器的...

    Microsoft.XMLHttp组件的属性方法

    Microsoft.XMLHttp组件的属性方法 XMLHTTP对象中的readyState属性其能够反映出服务器在处理请求时的进展状况。客户机的程序可以根据这个状态信息设置相应的事件处理方法

    谈XMLHTTP对象(属性和方法)-VBA抓取网页数据[参考].pdf

    1. 简洁易用:XMLHTTP 对象提供了一种简洁易用的方式来发送请求和接收回应。 2. 高效:XMLHTTP 对象可以快速地发送请求和接收回应。 3. 灵活:XMLHTTP 对象可以用来抓取网页数据、发送请求、分析回应等多种应用场景...

    Microsoft ADO Msxml2.ServerXMLHTTP Msxml2.XMLHTTP 程序员参考手册中文版CHM

    readyState 表示当前请求的状态,只读。 responseStream 表示一个作为Ado.Stream对象的应答实例,只读。 responseText 表示一个作为字符串的应答实例,只读。 responseXML 表示一个经MSXML解析过的应答实例,只读...

    javascript中ajax应用

    script&gt; function hq () {var xml; if(window.XMLHttpRequest) xml=new XMLHttpRequest(); else xml=new ActiveXObject("Microsoft... {if(xml.readyState==4&&xml.status==200)//当前状态是已结束时和请求成功时

    易语言XMLHTTP类模块

    易语言XMLHTTP类模块源码,XMLHTTP类模块,Status,StatusText,ResponseXML,ResponseText,ResponseBody,ResponseStream,ReadyState,onreadystatechange,Open,SetRequestHeader,GetResponseHeader,GetAllResponseHeaders...

    Ajax技术课件,保密资料下载

    * var xhr = new ActiveXObject("Microsoft.XMLHTTP"); var xhr = new ActiveXObject("MSXML2.5.0.XMLHTTP"); var xhr = new ActiveXObject("MSXML2.4.0.XMLHTTP"); 2 xhr相关的方法 建立连接 xhr.open(...

    ajax+php打造进度条 readyState各状态

    readyState == 状态(0,1,2,3,4) 0:请求未初始化,还没调用open 1:请求已经建立,但还没有发送,还没调用send 2:请求已发送,并且正在处理 3:请求正在处理,通常响应中已有部分数据可调用 4:完毕 复制代码 代码...

    ajax+php打造进度条代码[readyState各状态说明]

    readyState == 状态(0,1,2,3,4) 0:请求未初始化,还没调用open 1:请求已经建立,但还没有发送,还没调用send 2:请求已发送,并且正在处理 3:请求正在处理,通常响应中已有部分数据可调用 4:完毕 复制代码 代码...

    ajax运用实例得到的得到

    if (XMLHttpReq.readyState == 4) { // 判断对象状态 if (XMLHttpReq.status == 200) { // 信息已经成功返回,开始处理信息 var res=XMLHttpReq.responseXML.getElementsByTagName("res")[0].firstChild.data; ...

    jsp ajax实例

    if (XMLHttpReq.readyState == 4) { // 判断对象状态 if (XMLHttpReq.status == 200) { // 信息已经成功返回,开始处理信息 var res=XMLHttpReq.responseXML.getElementsByTagName("res")[0].firstChild.data; ...

    AJAX开发简略.pdf

    if (http_request.readyState == 4) { // 判断对象状态 if (http_request.status == 200) { // 信息已经成功返回,开始处理信息 alert&#40;http_request.responseText&#41;; } else { //页面不正常 alert&#40;...

    探讨Ajax中有关readyState(状态值)和status(状态码)的问题

    先看下面一段代码,然后给大家详细介绍,Ajax中有关readyState(状态值)和status(状态码)的问题,具体内容如下所示: var getXmlHttpRequest = function () { try{ //主流浏览器提供了XMLHttpRequest对象 return ...

    一个客户端的验证小程序ajax

    //第五步 发送请求 (输入数据) req.send(); //var newName ="uname=" + document.f3.uname.value; //req.send(newName); } //创建XMLHttpRequest对象 function createXMLHttpRequest() { if(window....

    易语言XMLHTTP类模块例程修改版

    易语言XMLHTTP类模块例程修改版源码,创建,打开,指定请求头数据,取响应头数据,取所有头数据,发送请求,取消当前请求,取状态码,取状态文本,取responseXML,取responseText,取响应数据,取responseStream,取readyState,置...

Global site tag (gtag.js) - Google Analytics