返回旧版| 微信建站| 建站之家论坛| 我要建站 | 建站学习 | 加入收藏
Ajax入门当前位置:首页 > HTML教程 > Ajax入门 > 正文

[四天学会ajax] 学习Ajax教程第二天(3)

发布时间:2013-07-29 13:06:00   来源:   点击:

发送请求

一旦用 open() 配置好之后,就可以发送请求了。幸运的是,发送请求的方法的名称要比 open() 适当,它就是 send()。

send() 只有一个参数,就是要发送的内容。但是在考虑这个方法之前,回想一下前面已经通过 URL 本身发送过数据了:

var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);

虽然可以使用 send() 发送数据,但也能通过 URL 本身发送数据。事实上,GET 请求(在典型的 Ajax 应用中大约占 80%)中,用 URL 发送数据要容易得多。如果需要发送安全信息或 XML,可能要考虑使用 send() 发送内容(本系列的后续文章中将讨论安全数据和 XML 消息)。如果不需要通过 send() 传递数据,则只要传递 null 作为该方法的参数即可。因此您会发现在本文中的例子中只需要这样发送请求(参见 清单 10)。

清单 10. 发送请求

function getCustomerInfo() {
var phone = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
request.open("GET", url, true);
request.send(null);
}

指定回调方法

现在我们所做的只有很少一点是新的、革命性的或异步的。必须承认,open() 方法中 “true” 这个小小的关键字建立了异步请求。但是除此之外,这些代码与用 Java servlet 及 JSP、PHP 或 Perl 编程没有什么两样。那么 Ajax 和 Web 2.0 最大的秘密是什么呢?秘密就在于 XMLHttpRequest 的一个简单属性 onreadystatechange。

首先一定要理解这些代码中的流程(如果需要请回顾 清单 10)。建立其请求然后发出请求。此外,因为是异步请求,所以 JavaScript 方法(例子中的 getCustomerInfo())不会等待服务器。因此代码将继续执行,就是说,将退出该方法而把控制返回给表单。用户可以继续输入信息,应用程序不会等待服务器。

这就提出了一个有趣的问题:服务器完成了请求之后会发生什么?答案是什么也不发生,至少对现在的代码而言如此!显然这样不行,因此服务器在完成通过 XMLHttpRequest 发送给它的请求处理之后需要某种指示说明怎么做。

在 JavaScript 中引用函数:
JavaScript 是一种弱类型的语言,可以用变量引用任何东西。因此如果声明了一个函数 updatePage(),JavaScript 也将该函数名看作是一个变量。换句话说,可用变量名 updatePage 在代码中引用函数。

清单 11. 设置回调方法

function getCustomerInfo() {
var phone = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
request.open("GET", url, true);
request.onreadystatechange = updatePage;
request.send(null);
}

需要特别注意的是该属性在代码中设置的位置 —— 它是在调用 send() 之前 设置的。发送请求之前必须设置该属性,这样服务器在回答完成请求之后才能查看该属性。现在剩下的就只有编写 updatePage() 方法了,这是本文最后一节要讨论的重点。

处理服务器响应

发送请求,用户高兴地使用 Web 表单(同时服务器在处理请求),而现在服务器完成了请求处理。服务器查看 onreadystatechange 属性确定要调用的方法。除此以外,可以将您的应用程序看作其他应用程序一样,无论是否异步。换句话说,不一定要采取特殊的动作编写响应服务器的方法,只需要改变表单,让用户访问另一个 URL 或者做响应服务器需要的任何事情。这一节我们重点讨论对服务器的响应和一种典型的动作 —— 即时改变用户看到的表单中的一部分
 

回调和 Ajax

现在我们已经看到如何告诉服务器完成后应该做什么:将 XMLHttpRequest 对象的 onreadystatechange 属性设置为要运行的函数名。这样,当服务器处理完请求后就会自动调用该函数。也不需要担心该函数的任何参数。我们从一个简单的方法开始,如 清单 12 所示。

清单 12. 回调方法的代码

  1. <script language="javascript" type="text/javascript"> 
  2. var request = false;  
  3. try {  
  4. request = new XMLHttpRequest();  
  5. } catch (trymicrosoft) {  
  6. try {  
  7. request = new ActiveXObject("Msxml2.XMLHTTP");  
  8. } catch (othermicrosoft) {  
  9. try {  
  10. request = new ActiveXObject("Microsoft.XMLHTTP");  
  11. } catch (failed) {  
  12. request = false;  
  13. }   
  14. }  
  15. }  
  16.  
  17. if (!request)  
  18. alert("Error initializing XMLHttpRequest!");  
  19.  
  20. function getCustomerInfo() {  
  21. var phone = document.getElementById("phone").value;  
  22. var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);  
  23. request.open("GET", url, true);  
  24. request.onreadystatechange = updatePage;  
  25. request.send(null);  
  26. }  
  27.  
  28. function updatePage() {  
  29. alert("Server is done!");  
  30. }  
  31. </script> 

它仅仅发出一些简单的警告,告诉您服务器什么时候完成了任务。在自己的网页中试验这些代码,然后在浏览器中打开(如果希望查看该例中的 XHTML,请参阅 清单 8)。输入电话号码然后离开该字段,将看到一个弹出的警告窗口(如 图 3 所示),但是点击 OK 又出现了……

图 3. 弹出警告的 Ajax 代码
 

 

[四天学会ajax] 学习Ajax教程第二天(3)
 
   根据浏览器的不同,在表单停止弹出警告之前会看到两次、三次甚至四次警告。这是怎么回事呢?原来我们还没有考虑 HTTP 就绪状态,这是请求/响应循环中的一个重要部分。

HTTP 就绪状态

前面提到,服务器在完成请求之后会在 XMLHttpRequest 的 onreadystatechange 属性中查找要调用的方法。这是真的,但还不完整。事实上,每当 HTTP 就绪状态改变时它都会调用该方法。这意味着什么呢?首先必须理解 HTTP 就绪状态。

HTTP 就绪状态表示请求的状态或情形。它用于确定该请求是否已经开始、是否得到了响应或者请求/响应模型是否已经完成。它还可以帮助确定读取服务器提供的响应文本或数据是否安全。在 Ajax 应用程序中需要了解五种就绪状态:

·0:请求没有发出(在调用 open() 之前)。

·1:请求已经建立但还没有发出(调用 send() 之前)。
·2:请求已经发出正在处理之中(这里通常可以从响应得到内容头部)。
·3:请求已经处理,响应中通常有部分数据可用,但是服务器还没有完成响应。
·4:响应已完成,可以访问服务器响应并使用它。

与大多数跨浏览器问题一样,这些就绪状态的使用也不尽一致。您也许期望任务就绪状态从 0 到 1、2、3 再到 4,但实际上很少是这种情况。一些浏览器从不报告 0 或 1 而直接从 2 开始,然后是 3 和 4。其他浏览器则报告所有的状态。还有一些则多次报告就绪状态 1。在上一节中看到,服务器多次调用 updatePage(),每次调用都会弹出警告框 —— 可能和预期的不同!

对于 Ajax 编程,需要直接处理的惟一状态就是就绪状态 4,它表示服务器响应已经完成,可以安全地使用响应数据了。基于此,回调方法中的第一行应该如 清单 13 所示。

清单 13. 检查就绪状态

function updatePage() {
if (request.readyState == 4)
alert("Server is done!");
}

修改后就可以保证服务器的处理已经完成。尝试运行新版本的 Ajax 代码,现在就会看到与预期的一样,只显示一次警告信息了。

HTTP 状态码

虽然 清单 13 中的代码看起来似乎不错,但是还有一个问题 —— 如果服务器响应请求并完成了处理但是报告了一个错误怎么办?要知道,服务器端代码应该明白它是由 Ajax、JSP、普通 HTML 表单或其他类型的代码调用的,但只能使用传统的 Web 专用方法报告信息。而在 Web 世界中,HTTP 代码可以处理请求中可能发生的各种问题。

比方说,您肯定遇到过输入了错误的 URL 请求而得到 404 错误码的情形,它表示该页面不存在。这仅仅是 HTTP 请求能够收到的众多错误码中的一种(完整的状态码列表请参阅 参考资料 中的链接)。表示所访问数据受到保护或者禁止访问的 403 和 401 也很常见。无论哪种情况,这些错误码都是从完成的响应 得到的。换句话说,服务器履行了请求(即 HTTP 就绪状态是 4)但是没有返回客户机预期的数据。

因此除了就绪状态外,还需要检查 HTTP 状态。我们期望的状态码是 200,它表示一切顺利。如果就绪状态是 4 而且状态码是 200,就可以处理服务器的数据了,而且这些数据应该就是要求的数据(而不是错误或者其他有问题的信息)。因此还要在回调方法中增加状态检查,如 清单 14 所示。

清单 14. 检查 HTTP 状态码

function updatePage() {
if (request.readyState == 4)
if (request.status == 200)
alert("Server is done!");
}

为了增加更健壮的错误处理并尽量避免过于复杂,可以增加一两个状态码检查,请看一看 清单 15 中修改后的 updatePage() 版本。

清单 15. 增加一点错误检查

function updatePage() {
if (request.readyState == 4)
if (request.status == 200)
alert("Server is done!");
else if (request.status == 404)
alert("Request URL does not exist");
else
 

alert("Error: status code is " + request.status);
}

现在将 getCustomerInfo() 中的 URL 改为不存在的 URL 看看会发生什么。应该会看到警告信息说明要求的 URL 不存在 —— 好极了!很难处理所有的错误条件,但是这一小小的改变能够涵盖典型 Web 应用程序中 80% 的问题。

读取响应文本

现在可以确保请求已经处理完成(通过就绪状态),服务器给出了正常的响应(通过状态码),最后我们可以处理服务器返回的数据了。返回的数据保存在 XMLHttpRequest 对象的 responseText 属性中。

关于 responseText 中的文本内容,比如格式和长度,有意保持含糊。这样服务器就可以将文本设置成任何内容。比方说,一种脚本可能返回逗号分隔的值,另一种则使用管道符(即 | 字符)分隔的值,还有一种则返回长文本字符串。何去何从由服务器决定。

在本文使用的例子中,服务器返回客户的上一个订单和客户地址,中间用管道符分开。然后使用订单和地址设置表单中的元素值,清单 16 给出了更新显示内容的代码。

清单 16. 处理服务器响应

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, "");
} else
alert("status is " + request.status);
}
}

首先,得到 responseText 并使用 JavaScript split() 方法从管道符分开。得到的数组放到 response 中。数组中的第一个值 —— 上一个订单 —— 用 response[0] 访问,被设置为 ID 为 “order” 的字段的值。第二个值 response[1],即客户地址,则需要更多一点处理。因为地址中的行用一般的行分隔符(“n”字符)分隔,代码中需要用 XHTML 风格的行分隔符 <br /> 来代替。替换过程使用 replace() 函数和正则表达式完成。最后,修改后的文本作为 HTML 表单 div 中的内部 HTML。结果就是表单突然用客户信息更新了,如图 4 所示。

图 4. 收到客户数据后的 Break Neck 表单

 

[四天学会ajax] 学习Ajax教程第二天(3)
 

 

 

   结束本文之前,我还要介绍 XMLHttpRequest 的另一个重要属性 responseXML。如果服务器选择使用 XML 响应则该属性包含(也许您已经猜到)XML 响应。处理 XML 响应和处理普通文本有很大不同,涉及到解析、文档对象模型(DOM)和其他一些问题。后面的文章中将进一步介绍 XML。但是因为 responseXML 通常和 responseText 一起讨论,这里有必要提一提。对于很多简单的 Ajax 应用程序 responseText 就够了,但是您很快就会看到通过 Ajax 应用程序也能很好地处理 XML
结束语

    您可能对 XMLHttpRequest 感到有点厌倦了,我很少看到一整篇文章讨论一个对象,特别是这种简单的对象。但是您将在使用 Ajax 编写的每个页面和应用程序中反复使用该对象。坦白地说,关于 XMLHttpRequest 还真有一些可说的内容。下一期文章中将介绍如何在请求中使用 POST 及 GET,来设置请求中的内容头部和从服务器响应读取内容头部,理解如何在请求/响应模型中编码请求和处理 XML。

   再往后我们将介绍常见 Ajax 工具箱。这些工具箱实际上隐藏了本文所述的很多细节,使得 Ajax 编程更容易。您也许会想,既然有这么多工具箱为何还要对底层的细节编码。答案是,如果不知道应用程序在做什么,就很难发现应用程序中的问题。

    因此不要忽略这些细节或者简单地浏览一下,如果便捷华丽的工具箱出现了错误,您就不必挠头或者发送邮件请求支持了。如果了解如何直接使用 XMLHttpRequest,就会发现很容易调试和解决最奇怪的问题。只有让其解决您的问题,工具箱才是好东西。

   因此请熟悉 XMLHttpRequest 吧。事实上,如果您有使用工具箱的 Ajax 代码,可以尝试使用 XMLHttpRequest 对象及其属性和方法重新改写。这是一种不错的练习,可以帮助您更好地理解其中的原理。

   下一期文章中将进一步讨论该对象,探讨它的一些更有趣的属性(如 responseXML),以及如何使用 POST 请求和以不同的格式发送数据。请开始编写代码吧,一个月后我们再继续讨论
 

 

版权所有:郑州腾石网络科技有限公司 备案信息:豫ICP备18019117号
站长QQ:2863868475 业务合作咨询:15137100750(同微信)
本站所有投放的广告是有其他网站提供,不代表本站立场,同时网站首页广告位对外出租详情咨询本站站长!同时欢迎广大站长加入个人建站团队
  • 建站客服
  • CMS仿站
  • CMS学习
  • 技术交流群:336572814