📄 掌握 ajax,第 2 部分 使用 javascript 和 ajax 发出异步请求.htm
字号:
width="100%"><BR><IMG height=6 alt=""
src="掌握 Ajax,第 2 部分 使用 JavaScript 和 Ajax 发出异步请求.files/c.gif"
width=8 border=0></TD></TR></TBODY></TABLE>
<TABLE class=no-print cellSpacing=0 cellPadding=0 align=right>
<TBODY>
<TR align=right>
<TD><IMG height=4 alt=""
src="掌握 Ajax,第 2 部分 使用 JavaScript 和 Ajax 发出异步请求.files/c.gif"
width="100%"><BR>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD vAlign=center><IMG height=16 alt=""
src="掌握 Ajax,第 2 部分 使用 JavaScript 和 Ajax 发出异步请求.files/u_bold.gif"
width=16 border=0><BR></TD>
<TD vAlign=top align=right><A class=fbox
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro2/#main"><B>回页首</B></A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
<P><A name=N102A0><SPAN class=atitle>用 XMLHttpRequest
发送请求</SPAN></A></P>
<P>得到请求对象之后就可以进入请求/响应循环了。记住,<CODE>XMLHttpRequest</CODE>
惟一的目的是让您发送请求和接收响应。其他一切都是 JavaScript、CSS
或页面中其他代码的工作:改变用户界面、切换图像、解释服务器返回的数据。准备好 <CODE>XMLHttpRequest</CODE>
之后,就可以向服务器发送请求了。</P>
<P><A name=N102B1><SPAN class=smalltitle>欢迎使用沙箱</SPAN></A></P>
<P>Ajax 采用一种沙箱安全模型。因此,Ajax 代码(具体来说就是 <CODE>XMLHttpRequest</CODE>
对象)只能对所在的同一个域发送请求。以后的文章中将进一步介绍安全和
Ajax,现在只要知道在本地机器上运行的代码只能对本地机器上的服务器端脚本发送请求。如果让 Ajax 代码在
www.breakneckpizza.com 上运行,则必须 www.breakneck.com 中运行的脚本发送请求。</P>
<P><A name=N102BD><SPAN class=smalltitle>设置服务器 URL</SPAN></A></P>
<P>首先要确定连接的服务器的 URL。这并不是 Ajax 的特殊要求,但仍然是建立连接所必需的,显然现在您应该知道如何构造 URL
了。多数应用程序中都会结合一些静态数据和用户处理的表单中的数据来构造该 URL。比如,<A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro2/#code7">清单
7</A> 中的 JavaScript 代码获取电话号码字段的值并用其构造 URL。</P><BR><BR><A
name=code7><B>清单 7. 建立请求 URL</B></A><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=code-outline><PRE class=displaycode>
<script language="javascript" type="text/javascript">
var request = false;
try {
request = new XMLHttpRequest();
} catch (trymicrosoft) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = false;
}
}
}
if (!request)
alert("Error initializing XMLHttpRequest!");
function getCustomerInfo() {
<SPAN class=boldcode>var phone = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);</SPAN>
}
</script>
</PRE></TD></TR></TBODY></TABLE><BR>
<P>这里没有难懂的地方。首先,代码创建了一个新变量 <CODE>phone</CODE>,并把 ID 为 “phone”
的表单字段的值赋给它。<A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro2/#code8">清单
8</A> 展示了这个表单的 XHTML,其中可以看到 <CODE>phone</CODE> 字段及其 <CODE>id</CODE>
属性。</P><BR><BR><A name=code8><B>清单 8. Break Neck Pizza
表单</B></A><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=code-outline><PRE class=displaycode>
<body>
<p><img src="breakneck-logo_4c.gif" alt="Break Neck Pizza" /></p>
<form action="POST">
<p>Enter your phone number:
<SPAN class=boldcode><input type="text" size="14" name="phone" id="phone"
onChange="getCustomerInfo();" /></SPAN>
</p>
<p>Your order will be delivered to:</p>
<div id="address"></div>
<p>Type your order in here:</p>
<p><textarea name="order" rows="6" cols="50" id="order"></textarea></p>
<p><input type="submit" value="Order Pizza" id="submit" /></p>
</form>
</body>
</PRE></TD></TR></TBODY></TABLE><BR>
<P>还要注意,当用户输入电话号码或者改变电话号码时,将触发 <A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro2/#code8">清单
8</A> 所示的 <CODE>getCustomerInfo()</CODE> 方法。该方法取得电话号码并构造存储在
<CODE>url</CODE> 变量中的 URL 字符串。记住,由于 Ajax 代码是沙箱型的,因而只能连接到同一个域,实际上 URL
中不需要域名。该例中的脚本名为 <CODE>/cgi-local/lookupCustomer.php</CODE>。最后,电话号码作为
GET 参数附加到该脚本中:<CODE>"phone=" + escape(phone)</CODE>。</P>
<P>如果以前没用见过 <CODE>escape()</CODE>
方法,它用于转义不能用明文正确发送的任何字符。比如,电话号码中的空格将被转换成字符 <CODE>%20</CODE>,从而能够在 URL
中传递这些字符。</P>
<P>可以根据需要添加任意多个参数。比如,如果需要增加另一个参数,只需要将其附加到 URL 中并用
“与”(<CODE>&</CODE>)字符分开 [第一个参数用问号(<CODE>?</CODE>)和脚本名分开]。</P>
<P><A name=N10323><SPAN class=smalltitle>打开请求</SPAN></A></P>
<TABLE cellSpacing=0 cellPadding=0 width="45%" align=right
border=0><TBODY>
<TR>
<TD width=10><IMG height=1 alt=""
src="掌握 Ajax,第 2 部分 使用 JavaScript 和 Ajax 发出异步请求.files/c.gif"
width=10></TD>
<TD>
<TABLE cellSpacing=0 cellPadding=5 width="100%" border=1>
<TBODY>
<TR>
<TD bgColor=#eeeeee><A name=N1032C><B>open()
是打开吗?</B></A><BR>Internet 开发人员对 <CODE>open()</CODE>
方法到底做什么没有达成一致。但它实际上并<I>不是</I> 打开一个请求。如果监控 XHTML/Ajax
页面及其连接脚本之间的网络和数据传递,当调用 <CODE>open()</CODE>
方法时将看不到任何通信。不清楚为何选用了这个名字,但显然不是一个好的选择。
</TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<P>有了要连接的 URL 后就可以配置请求了。可以用 <CODE>XMLHttpRequest</CODE> 对象的
<CODE>open()</CODE> 方法来完成。该方法有五个参数:</P>
<UL>
<LI><I>request-type</I>:发送请求的类型。典型的值是 <CODE>GET</CODE> 或
<CODE>POST</CODE>,但也可以发送 <CODE>HEAD</CODE> 请求。
<LI><I>url</I>:要连接的 URL。
<LI><I>asynch</I>:如果希望使用异步连接则为 true,否则为 false。该参数是可选的,默认为 true。
<LI><I>username</I>:如果需要身份验证,则可以在此指定用户名。该可选参数没有默认值。
<LI><I>password</I>:如果需要身份验证,则可以在此指定口令。该可选参数没有默认值。 </LI></UL>
<P>通常使用其中的前三个参数。事实上,即使需要异步连接,也应该指定第三个参数为
“true”。这是默认值,但坚持明确指定请求是异步的还是同步的更容易理解。</P>
<P>将这些结合起来,通常会得到 <A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro2/#code9">清单
9</A> 所示的一行代码。</P><BR><BR><A name=code9><B>清单 9. 打开请求</B></A><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=code-outline><PRE class=displaycode>
function getCustomerInfo() {
var phone = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
<SPAN class=boldcode>request.open("GET", url, true);</SPAN>
}
</PRE></TD></TR></TBODY></TABLE><BR>
<P>一旦设置好了 URL,其他就简单了。多数请求使用 <CODE>GET</CODE> 就够了(后面的文章中将看到需要使用
<CODE>POST</CODE> 的情况),再加上 URL,这就是使用 <CODE>open()</CODE>
方法需要的全部内容了。</P>
<P><A name=N10396><SPAN class=smalltitle>挑战异步性</SPAN></A></P>
<P>本系列的后面一篇文章中,我将用很多时间编写和使用异步代码,但是您应该明白为什么 <CODE>open()</CODE>
的最后一个参数这么重要。在一般的请求/响应模型中,比如 Web
1.0,客户机(浏览器或者本地机器上运行的代码)向服务器发出请求。该请求是同步的,换句话说,客户机等待服务器的响应。当客户机等待的时候,至少会用某种形式通知您在等待:</P>
<UL>
<LI>沙漏(特别是 Windows 上)。
<LI>旋转的皮球(通常在 Mac 机器上)。
<LI>应用程序基本上冻结了,然后过一段时间光标变化了。 </LI></UL>
<P>这正是 Web 应用程序让人感到笨拙或缓慢的原因 ——
缺乏真正的交互性。按下按钮时,应用程序实际上变得不能使用,直到刚刚触发的请求得到响应。如果请求需要大量服务器处理,那么等待的时间可能很长(至少在这个多处理器、DSL
没有等待的世界中是如此)。</P>
<P>而异步请求<I>不</I> 等待服务器响应。发送请求后应用程序继续运行。用户仍然可以在 Web
表单中输入数据,甚至离开表单。没有旋转的皮球或者沙漏,应用程序也没有明显的冻结。服务器悄悄地响应请求,完成后告诉原来的请求者工作已经结束(具体的办法很快就会看到)。结果是,应用程序感觉<I>不</I>
那么迟钝或者缓慢,而是响应迅速、交互性强,感觉快多了。这仅仅是 Web 2.0 的一部分,但它是很重要的一部分。所有老套的 GUI
组件和 Web 设计范型都不能克服缓慢、同步的请求/响应模型。</P>
<P><A name=N103BA><SPAN class=smalltitle>发送请求</SPAN></A></P>
<P>一旦用 <CODE>open()</CODE> 配置好之后,就可以发送请求了。幸运的是,发送请求的方法的名称要比
<CODE>open()</CODE> 适当,它就是 <CODE>send()</CODE>。</P>
<P><CODE>send()</CODE> 只有一个参数,就是要发送的内容。但是在考虑这个方法之前,回想一下前面已经通过 URL
本身发送过数据了:</P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=code-outline><PRE class=displaycode>var url = "/cgi-local/lookupCustomer.php?<SPAN class=boldcode>phone=" + escape(phone);</SPAN>
</PRE></TD></TR></TBODY></TABLE><BR>
<P>虽然可以使用 <CODE>send()</CODE> 发送数据,但也能通过 URL
本身发送数据。事实上,<CODE>GET</CODE> 请求(在典型的 Ajax 应用中大约占 80%)中,用 URL
发送数据要容易得多。如果需要发送安全信息或 XML,可能要考虑使用 <CODE>send()</CODE>
发送内容(本系列的后续文章中将讨论安全数据和 XML 消息)。如果不需要通过 <CODE>send()</CODE>
传递数据,则只要传递 <CODE>null</CODE> 作为该方法的参数即可。因此您会发现在本文中的例子中只需要这样发送请求(参见
<A
href="http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro2/#code10">清单
10</A>)。</P><BR><BR><A name=code10><B>清单 10. 发送请求</B></A><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=code-outline><PRE class=displaycode>
function getCustomerInfo() {
var phone = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
request.open("GET", url, true);
<SPAN class=boldcode>request.send(null);</SPAN>
}
</PRE></TD></TR></TBODY></TABLE><BR>
<P><A name=N10404><SPAN class=smalltitle>指定回调方法</SPAN></A></P>
<P>现在我们所做的只有很少一点是新的、革
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -