📄 掌握 ajax,第 3 部分 ajax 中的高级请求和响应.htm
字号:
function getSalesData() {
// Create a request object
createRequest();
<SPAN class=boldcode>alert("Ready state is: " + request.readyState);</SPAN>
// Setup (initialize) the request
var url = "/boards/servlet/UpdateBoardSales";
request.open("GET", url, true);
request.onreadystatechange = updatePage;
request.send(null);
}
</PRE></TD></TR></TBODY></TABLE><BR>
<P>在这个简单的例子中,<CODE>getSalesData()</CODE> 是 Web
页面调用来启动请求(例如点击一个按钮时)所使用的函数。注意您必须在调用 <CODE>open()</CODE> <I>之前</I>
来查看就绪状态。<A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro3/#fig1">图
1</A> 给出了运行这个应用程序的结果。</P><BR><BR><A name=fig1><B>图 1. 就绪状态
0</B></A><BR><IMG height=329 alt="就绪状态 0"
src="掌握 Ajax,第 3 部分 Ajax 中的高级请求和响应.files/ready-state_0.jpg"
width=500> <BR>
<TABLE cellSpacing=0 cellPadding=0 width="50%" align=right
border=0><TBODY>
<TR>
<TD width=10><IMG height=1 alt=""
src="掌握 Ajax,第 3 部分 Ajax 中的高级请求和响应.files/c.gif" width=10></TD>
<TD>
<TABLE cellSpacing=0 cellPadding=5 width="100%" border=1>
<TBODY>
<TR>
<TD bgColor=#eeeeee><A name=N1016E><B>当 0 等于 4
时</B></A><BR>
<P>在多个 JavaScript 函数都使用相同的请求对象时,您需要检查就绪状态 0
来确保这个请求对象没有正在使用,这种机制会产生问题。由于 <CODE>readyState ==
4</CODE> 表示一个已完成的请求,因此您经常会发现那些目前没在使用的处于就绪状态的请求对象仍然被设置成了
4 —— 这是因为从服务器返回来的数据已经使用过了,但是从它们被设置为就绪状态之后就没有进行任何变化。有一个函数
<CODE>abort()</CODE> 会重新设置请求对象,但是这个函数却不是真正为了这个目的而使用的。如果您
<I>必须</I>
使用多个函数,最好是为每个函数都创建并使用一个函数,而不是在多个函数之间共享相同的对象。</P></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<P>显然,这并不能为您带来多少好处;需要确保 <I>尚未</I> 调用 <CODE>open()</CODE>
函数的情况很少。在大部分 Ajax 编程的真实情况中,这种就绪状态的唯一用法就是使用相同的
<CODE>XMLHttpRequest</CODE>
对象在多个函数之间生成多个请求。在这种(不常见的)情况中,您可能会在生成新请求之前希望确保请求对象是处于未初始化状态(<CODE>readyState
== 0</CODE>)。这实际上是要确保另外一个函数没有同时使用这个对象。</P>
<P><A name=N10194><SPAN
class=smalltitle>查看正在处理的请求的就绪状态</SPAN></A></P>
<P>除了 0 就绪状态之外,请求对象还需要依次经历典型的请求和响应的其他几种就绪状态,最后才以就绪状态 4
的形式结束。这就是为什么您在大部分回调函数中都可以看到 <CODE>if (request.readyState ==
4)</CODE> 这行代码;它确保服务器已经完成对请求的处理,现在可以安全地更新 Web
页面或根据从服务器返回来的数据来进行操作了。</P>
<P>要查看这种状态发生的过程非常简单。如果就绪状态为 4,我们不仅要运行回调函数中的代码,而且还要在每次调用回调函数时都输出就绪状态。
<A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro3/#listing3">清单
3</A> 给出了一个实现这种功能的例子。</P><BR><BR><A name=listing3><B>清单 3.
查看就绪状态</B></A><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=code-outline><PRE class=displaycode>
function updatePage() {
// Output the current ready state
alert("updatePage() called with ready state of " + request.readyState);
}
</PRE></TD></TR></TBODY></TABLE><BR>
<P>如果您不确定如何运行这个函数,就需要创建一个函数,然后在 Web 页面中调用这个函数,并让它向服务器端的组件发送一个请求(例如
<A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro3/#listing2">清单
2</A> 给出的函数,或本系列文章的第 1 部分和第 2 部分中给出的例子)。确保在建立请求时,将回调函数设置为
<CODE>updatePage()</CODE>;要实现这种设置,可以将请求对象的
<CODE>onreadystatechange</CODE> 属性设置为 <CODE>updatePage()</CODE>。</P>
<P>这段代码就是 <CODE>onreadystatechange</CODE> 意义的一个确切展示 ——
每次请求的就绪状态发生变化时,就调用 <CODE>updatePage()</CODE>,然后我们就可以看到一个警告了。<A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro3/#fig2">图
2</A> 给出了一个调用这个函数的例子,其中就绪状态为 1。</P><BR><BR><A name=fig2><B>图 2. 就绪状态
1</B></A><BR><IMG height=328 alt="就绪状态 1"
src="掌握 Ajax,第 3 部分 Ajax 中的高级请求和响应.files/ready-state_1.jpg"
width=500> <BR>
<P>您可以自己尝试运行这段代码。将其放入 Web 页面中,然后激活事件处理程序(单击按钮,在域之间按 tab
键切换焦点,或者使用设置的任何方法来触发请求)。这个回调函数会运行多次 —— 每次就绪状态都会改变 ——
您可以看到每个就绪状态的警告。这是跟踪请求所经历的各个阶段的最好方法。</P>
<P><A name=N101E7><SPAN class=smalltitle>浏览器的不一致性</SPAN></A></P>
<P>在对这个过程有一个基本的了解之后,请试着从几个不同的浏览器中访问您的页面。您应该会注意到各个浏览器如何处理这些就绪状态并不一致。例如,在
Firefox 1.5 中,您会看到以下就绪状态:</P>
<UL>
<LI>1
<LI>2
<LI>3
<LI>4 </LI></UL>
<P>这并不奇怪,因为每个请求状态都在这里表示出来了。然而,如果您使用 Safari 来访问相同的应用程序,就应该看到 —— 或者看不到
—— 一些有趣的事情。下面是在 Safari 2.0.1 中看到的状态:</P>
<UL>
<LI>2
<LI>3
<LI>4 </LI></UL>
<P>Safari 实际上把第一个就绪状态给丢弃了,也并没有什么明显的原因说明为什么要这样做;不过这就是 Safari
的工作方式。这还说明了一个重要的问题:<I>尽管在使用服务器上的数据之前确保请求的状态为 4
是一个好主意,但是依赖于每个过渡期就绪状态编写的代码的确会在不同的浏览器上得到不同的结果</I>。</P>
<P>例如,在使用 Opera 8.5 时,所显示的就绪状态情况就更加糟糕了:</P>
<UL>
<LI>3
<LI>4 </LI></UL>
<P>最后,Internet Explorer 会显示如下状态:</P>
<UL>
<LI>1
<LI>2
<LI>3
<LI>4 </LI></UL>
<P>如果您碰到请求方面的问题,这就是用来发现问题的 <I>首要之处</I>。最好的方式是在 Internet Explorer 和
Firefox 都进行一下测试 —— 您会看到所有这 4 种状态,并可以检查请求的每个状态所处的情况。</P>
<P>接下来我们再来看一下响应端的情况。</P>
<P><A name=N1023B><SPAN class=atitle>显微镜下的响应数据</SPAN></A></P>
<P>一旦我们理解在请求过程中发生的各个就绪状态之后,接下来就可以来看一下 <CODE>XMLHttpRequest</CODE>
对象的另外一个方面了 —— <CODE>responseText</CODE>
属性。回想一下在上一篇文章中我们介绍过的内容,就可以知道这个属性用来从服务器上获取数据。一旦服务器完成对请求的处理之后,就可以将响应请求数据所需要的任何数据放到请求的
<CODE>responseText</CODE> 中了。然后回调函数就可以使用这些数据,如 <A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro3/#listing1">清单
1</A> 和 <A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro3/#listing4">清单
4</A> 所示。</P><BR><BR><A name=listing4><B>清单 4.
使用服务器上返回的响应</B></A><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=code-outline><PRE class=displaycode>
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);
}
</PRE></TD></TR></TBODY></TABLE><BR>
<P><A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro3/#listing1">清单
1</A> 相当简单;<A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro3/#listing4">清单
4</A> 稍微有点复杂,但是它们在开始时都要检查就绪状态,并获取 <CODE>responseText</CODE>
属性的值。</P>
<P><A name=N10272><SPAN class=smalltitle>查看请求的响应文本</SPAN></A></P>
<P>与就绪状态类似,<CODE>responseText</CODE>
属性的值在整个请求的生命周期中也会发生变化。要查看这种变化,请使用如 <A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro3/#listing5">清单
5</A> 所示的代码来测试请求的响应文本,以及它们的就绪状态。</P><BR><BR><A name=listing5><B>清单
5. 测试 responseText 属性</B></A><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=code-outline><PRE class=displaycode>
function updatePage() {
// Output the current ready state
alert("updatePage() called with ready state of " + request.readyState +
" and a response text of '" + request.responseText + "'");
}
</PRE></TD></TR></TBODY></TABLE><BR>
<P>现在在浏览器中打开 Web 应用程序,并激活您的请求。要更好地看到这段代码的效果,请使用 Firefox 或 Internet
Explorer,因为这两个浏览器都可以报告出请求过程中所有可能的就绪状态。例如在就绪状态 2 中,就没有定义
<CODE>responseText</CODE> (请参见 <A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro3/#fig3">图
3</A>);如果 JavaScript 控制台也已经打开了,您就会看到一个错误。</P><BR><BR><A
name=fig3><B>图 3. 就绪状态为 2 的响应文本</B></A><BR><IMG height=333
alt="就绪状态为 2 的响应文本"
src="掌握 Ajax,第 3 部分 Ajax 中的高级请求和响应.files/ready-state_2.jpg"
width=500> <BR>
<P>不过在就绪状态 3 中,服务器已经在 <CODE>responseText</CODE>
属性中放上了一个值,至少在这个例子中是这样(请参见 <A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro3/#fig4">图
4</A>)。</P><BR><BR><A name=fig4><B>图 4. 就绪状态为 3
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -