苏州专业网站设计制作公司,网站核验通知书,河南省建设厅网站地址,门户网站建设内转http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro2/ 掌握 Ajax#xff0c;第 2 部分: 使用 JavaScript 和 Ajax 发出异步请求 在 Web 请求中使用 XMLHttpRequest 多数 Web 应用程序都使用请求/响应模型从服务器上获得完整的 HTML 页面。常常是点击一个按钮#xff0… 转http://www.ibm.com/developerworks/cn/xml/wa-ajaxintro2/ 掌握 Ajax第 2 部分: 使用 JavaScript 和 Ajax 发出异步请求 在 Web 请求中使用 XMLHttpRequest 多数 Web 应用程序都使用请求/响应模型从服务器上获得完整的 HTML 页面。常常是点击一个按钮等待服务器响应再点击另一个按钮然后再等待这样一个反复的过程。有了 Ajax 和 XMLHttpRequest 对象就可以使用不必让用户等待服务器响应的请求/响应模型了。本文中Brett McLaughlin 介绍了如何创建能够适应不同浏览器的 XMLHttpRequest 实例建立和发送请求并响应服务器。 查看本系列更多内容 | 14 评论 Brett McLaughlin (brettnewInstance.com), 作家编辑, OReilly Media Inc. 2006 年 2 月 16 日 内容 在 IBM Bluemix 云平台上开发并部署您的下一个应用。 开始您的试用 本系列的上一期文章请参阅 参考资料 中的链接我们介绍了 Ajax 应用程序考察了推动 Ajax 应用程序的基本概念。其中的核心是很多您可能已经了解的技术JavaScript、HTML 和 XHTML、一点动态 HTML 以及 DOM文档对象模型。本文将放大其中的一点把目光放到具体的 Ajax 细节上。 本文中您将开始接触最基本和基础性的有关 Ajax 的全部对象和编程方法XMLHttpRequest 对象。该对象实际上仅仅是一个跨越所有 Ajax 应用程序的公共线程您可能已经预料到只有彻底理解该对象才能充分发挥编程的潜力。事实上有时您会发现要正确地使用 XMLHttpRequest显然不能 使用XMLHttpRequest。这到底是怎么回事呢 Web 2.0 一瞥 在深入研究代码之前首先看看最近的观点 —— 一定要十分清楚 Web 2.0 这个概念。听到 Web 2.0 这个词的时候应该首先问一问 “Web 1.0 是什么” 虽然很少听人提到 Web 1.0实际上它指的就是具有完全不同的请求和响应模型的传统 Web。比如到 Amazon.com 网站上点击一个按钮或者输入搜索项。就会对服务器发送一个请求然后响应再返回到浏览器。该请求不仅仅是图书和书目列表而是另一个完整的 HTML 页面。因此当 Web 浏览器用新的 HTML 页面重绘时可能会看到闪烁或抖动。事实上通过看到的每个新页面可以清晰地看到请求和响应。 Web 2.0在很大程度上消除了这种看得见的往复交互。比如访问 Google Maps 或 Flickr 这样的站点到这些支持 Web 2.0 和 Ajax 站点的链接请参阅 参考资料。比如在 Google Maps 上您可以拖动地图放大和缩小只有很少的重绘操作。当然这里仍然有请求和响应只不过都藏到了幕后。作为用户体验更加舒适感觉很像桌面应用程序。这种新的感受和范型就是当有人提到 Web 2.0 时您所体会到的。 需要关心的是如何使这些新的交互成为可能。显然仍然需要发出请求和接收响应但正是针对每次请求/响应交互的 HTML 重绘造成了缓慢、笨拙的 Web 交互的感受。因此很清楚我们需要一种方法使发送的请求和接收的响应只 包含需要的数据而不是整个 HTML 页面。惟一需要获得整个新 HTML 页面的时候就是希望用户看到 新页面的时候。 但多数交互都是在已有页面上增加细节、修改主体文本或者覆盖原有数据。这些情况下Ajax 和 Web 2.0 方法允许在不 更新整个 HTML 页面的情况下发送和接收数据。对于那些经常上网的人这种能力可以让您的应用程序感觉更快、响应更及时让他们不时地光顾您的网站。 回页首 XMLHttpRequest 简介 要真正实现这种绚丽的奇迹必须非常熟悉一个 JavaScript 对象即 XMLHttpRequest。这个小小的对象实际上已经在几种浏览器中存在一段时间了它是本专栏今后几个月中要介绍的 Web 2.0、Ajax 和大部分其他内容的核心。为了让您快速地大体了解它下面给出将要用于该对象的很少的几个 方法和属性。 open()建立到服务器的新请求。send()向服务器发送请求。abort()退出当前请求。readyState提供当前 HTML 的就绪状态。responseText服务器返回的请求响应文本。如果不了解这些或者其中的任何 一个您也不用担心后面几篇文章中我们将介绍每个方法和属性。现在应该 了解的是明确用XMLHttpRequest 做什么。要注意这些方法和属性都与发送请求及处理响应有关。事实上如果看到 XMLHttpRequest 的所有方法和属性就会发现它们都 与非常简单的请求/响应模型有关。显然我们不会遇到特别新的 GUI 对象或者创建用户交互的某种超极神秘的方法我们将使用非常简单的请求和非常简单的响应。听起来似乎没有多少吸引力但是用好该对象可以彻底改变您的应用程序。 简单的 new 首先需要创建一个新变量并赋给它一个 XMLHttpRequest 对象实例。这在 JavaScript 中很简单只要对该对象名使用 new 关键字即可如 清单 1 所示。 清单 1. 创建新的 XMLHttpRequest 对象 script languagejavascript typetext/javascript
var request new XMLHttpRequest();
/script 不难吧记住JavaScript 不要求指定变量类型因此不需要像 清单 2 那样做在 Java 语言中可能需要这样。 清单 2. 创建 XMLHttpRequest 的 Java 伪代码 XMLHttpRequest request new XMLHttpRequest(); 因此在 JavaScript 中用 var 创建一个变量给它一个名字如 “request”然后赋给它一个新的 XMLHttpRequest 实例。此后就可以在函数中使用该对象了。 错误处理 在实际上各种事情都可能出错而上面的代码没有提供任何错误处理。较好的办法是创建该对象并在出现问题时优雅地退出。比如任何较早的浏览器不论您是否相信仍然有人在使用老版本的 Netscape Navigator都不支持 XMLHttpRequest您需要让这些用户知道有些地方出了问题。清单 3 说明如何创建该对象以便在出现问题的时候发出 JavaScript 警告。 清单 3. 创建具有错误处理能力的 XMLHttpRequest script languagejavascript typetext/javascript
var request false;
try {request new XMLHttpRequest();
} catch (failed) {request false;
}
if (!request)alert(Error initializing XMLHttpRequest!);
/script 一定要理解这些步骤 创建一个新变量 request 并赋值 false。后面将使用 false 作为判定条件它表示还没有创建 XMLHttpRequest 对象。增加 try/catch 块尝试创建 XMLHttpRequest 对象。如果失败catch (failed)则保证 request 的值仍然为 false。检查 request 是否仍为 false如果一切正常就不会是 false。如果出现问题request 是 false则使用 JavaScript 警告通知用户出现了问题。代码非常简单对大多数 JavaScript 和 Web 开发人员来说真正理解它要比读写代码花更长的时间。现在已经得到了一段带有错误检查的XMLHttpRequest 对象创建代码还可以告诉您哪儿出了问题。 应付 Microsoft 看起来似乎一切良好至少在用 Internet Explorer 试验这些代码之前是这样的。如果这样试验的话就会看到 图 1 所示的糟糕情形。 图 1. Internet Explorer 报告错误 Microsoft 参与了吗 关于 Ajax 和 Microsoft 对该领域不断增长的兴趣和参与已经有很多文章进行了介绍。事实上据说 Microsoft 最新版本的 Internet Explorer —— version 7.0将在 2006 年下半年推出 —— 将开始直接支持 XMLHttpRequest让您使用 new 关键字代替所有的 Msxml2.XMLHTTP 创建代码。但不要太激动仍然需要支持旧的浏览器因此跨浏览器代码不会很快消失。 显然有什么地方不对劲而 Internet Explorer 很难说是一种过时的浏览器因为全世界有 70% 在使用 Internet Explorer。换句话说如果不支持 Microsoft 和 Internet Explorer 就不会受到 Web 世界的欢迎因此我们需要采用不同的方法处理 Microsoft 浏览器。 经验证发现 Microsoft 支持 Ajax但是其 XMLHttpRequest 版本有不同的称呼。事实上它将其称为几种 不同的东西。如果使用较新版本的 Internet Explorer则需要使用对象 Msxml2.XMLHTTP而较老版本的 Internet Explorer 则使用 Microsoft.XMLHTTP。我们需要支持这两种对象类型同时还要支持非 Microsoft 浏览器。请看看 清单 4它在前述代码的基础上增加了对 Microsoft 的支持。 清单 4. 增加对 Microsoft 浏览器的支持 script languagejavascript typetext/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!);
/script 很容易被这些花括号迷住了眼睛因此下面分别介绍每一步 创建一个新变量 request 并赋值 false。使用 false 作为判断条件它表示还没有创建 XMLHttpRequest 对象。增加 try/catch 块尝试创建 XMLHttpRequest 对象。如果失败catch (trymicrosoft)尝试使用较新版本的 Microsoft 浏览器创建 Microsoft 兼容的对象Msxml2.XMLHTTP。如果失败catch (othermicrosoft)尝试使用较老版本的 Microsoft 浏览器创建 Microsoft 兼容的对象Microsoft.XMLHTTP。如果失败catch (failed)则保证 request 的值仍然为 false。检查 request 是否仍然为 false如果一切顺利就不会是 false。如果出现问题request 是 false则使用 JavaScript 警告通知用户出现了问题。这样修改代码之后再使用 Internet Explorer 试验就应该看到已经创建的表单没有错误消息。我实验的结果如 图 2 所示。 图 2. Internet Explorer 正常工作 静态与动态 再看一看清单 1、3 和 4注意所有这些代码都直接嵌套在 script 标记中。像这种不放到方法或函数体中的 JavaScript 代码称为静态 JavaScript。就是说代码是在页面显示给用户之前的某个时候运行。虽然根据规范不能完全精确地 知道这些代码何时运行对浏览器有什么影响但是可以保证这些代码在用户能够与页面交互之前运行。这也是多数 Ajax 程序员创建 XMLHttpRequest 对象的一般方式。 就是说也可以像 清单 5 那样将这些代码放在一个方法中。 清单 5. 将 XMLHttpRequest 创建代码移动到方法中 script languagejavascript typetext/javascript
var request;
function createRequest() {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!);
}
/script 如果按照这种方式编写代码那么在处理 Ajax 之前需要调用该方法。因此还需要 清单 6 这样的代码。 清单 6. 使用 XMLHttpRequest 的创建方法 script languagejavascript typetext/javascript
var request;
function createRequest() {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() {createRequest();// Do something with the request variable
}
/script 此代码惟一的问题是推迟了错误通知这也是多数 Ajax 程序员不采用这一方法的原因。假设一个复杂的表单有 10 或 15 个字段、选择框等当用户在第 14 个字段按照表单顺序从上到下输入文本时要激活某些 Ajax 代码。这时候运行 getCustomerInfo() 尝试创建一个XMLHttpRequest 对象但对于本例来说失败了。然后向用户显示一条警告明确地告诉他们不能使用该应用程序。但用户已经花费了很多时间在表单中输入数据这是非常令人讨厌的而讨厌显然不会吸引用户再次访问您的网站。 如果使用静态 JavaScript用户在点击页面的时候很快就会看到错误信息。这样也很烦人是不是可能令用户错误地认为您的 Web 应用程序不能在他的浏览器上运行。不过当然要比他们花费了 10 分钟输入信息之后再显示同样的错误要好。因此我建议编写静态的代码让用户尽可能早地发现问题。 回页首 用 XMLHttpRequest 发送请求 得到请求对象之后就可以进入请求/响应循环了。记住XMLHttpRequest 惟一的目的是让您发送请求和接收响应。其他一切都是 JavaScript、CSS 或页面中其他代码的工作改变用户界面、切换图像、解释服务器返回的数据。准备好 XMLHttpRequest 之后就可以向服务器发送请求了。 欢迎使用沙箱 Ajax 采用一种沙箱安全模型。因此Ajax 代码具体来说就是 XMLHttpRequest 对象只能对所在的同一个域发送请求。以后的文章中将进一步介绍安全和 Ajax现在只要知道在本地机器上运行的代码只能对本地机器上的服务器端脚本发送请求。如果让 Ajax 代码在 www.breakneckpizza.com 上运行则必须 www.breakneck.com 中运行的脚本发送请求。 设置服务器 URL 首先要确定连接的服务器的 URL。这并不是 Ajax 的特殊要求但仍然是建立连接所必需的显然现在您应该知道如何构造 URL 了。多数应用程序中都会结合一些静态数据和用户处理的表单中的数据来构造该 URL。比如清单 7 中的 JavaScript 代码获取电话号码字段的值并用其构造 URL。 清单 7. 建立请求 URL script languagejavascript typetext/javascriptvar 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() {var phone document.getElementById(phone).value;var url /cgi-local/lookupCustomer.php?phone escape(phone);}
/script 这里没有难懂的地方。首先代码创建了一个新变量 phone并把 ID 为 “phone” 的表单字段的值赋给它。清单 8 展示了这个表单的 XHTML其中可以看到 phone 字段及其 id 属性。 清单 8. Break Neck Pizza 表单 bodypimg srcbreakneck-logo_4c.gif altBreak Neck Pizza //pform actionPOSTpEnter your phone number:input typetext size14 namephone idphone onChangegetCustomerInfo(); //ppYour order will be delivered to:/pdiv idaddress/divpType your order in here:/pptextarea nameorder rows6 cols50 idorder/textarea/ppinput typesubmit valueOrder Pizza idsubmit //p/form/body 还要注意当用户输入电话号码或者改变电话号码时将触发 清单 8 所示的 getCustomerInfo() 方法。该方法取得电话号码并构造存储在url 变量中的 URL 字符串。记住由于 Ajax 代码是沙箱型的因而只能连接到同一个域实际上 URL 中不需要域名。该例中的脚本名为/cgi-local/lookupCustomer.php。最后电话号码作为 GET 参数附加到该脚本中phone escape(phone)。 如果以前没用见过 escape() 方法它用于转义不能用明文正确发送的任何字符。比如电话号码中的空格将被转换成字符 %20从而能够在 URL 中传递这些字符。 可以根据需要添加任意多个参数。比如如果需要增加另一个参数只需要将其附加到 URL 中并用 “与”字符分开 [第一个参数用问号?和脚本名分开]。 打开请求 open() 是打开吗 Internet 开发人员对 open() 方法到底做什么没有达成一致。但它实际上并不是 打开一个请求。如果监控 XHTML/Ajax 页面及其连接脚本之间的网络和数据传递当调用 open() 方法时将看不到任何通信。不清楚为何选用了这个名字但显然不是一个好的选择。 有了要连接的 URL 后就可以配置请求了。可以用 XMLHttpRequest 对象的 open() 方法来完成。该方法有五个参数 request-type发送请求的类型。典型的值是 GET 或 POST但也可以发送 HEAD 请求。url要连接的 URL。asynch如果希望使用异步连接则为 true否则为 false。该参数是可选的默认为 true。username如果需要身份验证则可以在此指定用户名。该可选参数没有默认值。password如果需要身份验证则可以在此指定口令。该可选参数没有默认值。通常使用其中的前三个参数。事实上即使需要异步连接也应该指定第三个参数为 “true”。这是默认值但坚持明确指定请求是异步的还是同步的更容易理解。 将这些结合起来通常会得到 清单 9 所示的一行代码。 清单 9. 打开请求 function getCustomerInfo() {var phone document.getElementById(phone).value;var url /cgi-local/lookupCustomer.php?phone escape(phone);request.open(GET, url, true);} 一旦设置好了 URL其他就简单了。多数请求使用 GET 就够了后面的文章中将看到需要使用 POST 的情况再加上 URL这就是使用open() 方法需要的全部内容了。 挑战异步性 本系列的后面一篇文章中我将用很多时间编写和使用异步代码但是您应该明白为什么 open() 的最后一个参数这么重要。在一般的请求/响应模型中比如 Web 1.0客户机浏览器或者本地机器上运行的代码向服务器发出请求。该请求是同步的换句话说客户机等待服务器的响应。当客户机等待的时候至少会用某种形式通知您在等待 沙漏特别是 Windows 上。旋转的皮球通常在 Mac 机器上。应用程序基本上冻结了然后过一段时间光标变化了。这正是 Web 应用程序让人感到笨拙或缓慢的原因 —— 缺乏真正的交互性。按下按钮时应用程序实际上变得不能使用直到刚刚触发的请求得到响应。如果请求需要大量服务器处理那么等待的时间可能很长至少在这个多处理器、DSL 没有等待的世界中是如此。 而异步请求不 等待服务器响应。发送请求后应用程序继续运行。用户仍然可以在 Web 表单中输入数据甚至离开表单。没有旋转的皮球或者沙漏应用程序也没有明显的冻结。服务器悄悄地响应请求完成后告诉原来的请求者工作已经结束具体的办法很快就会看到。结果是应用程序感觉不 那么迟钝或者缓慢而是响应迅速、交互性强感觉快多了。这仅仅是 Web 2.0 的一部分但它是很重要的一部分。所有老套的 GUI 组件和 Web 设计范型都不能克服缓慢、同步的请求/响应模型。 发送请求 一旦用 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 在代码中引用函数。 现在 onreadystatechange 属性该登场了。该属性允许指定一个回调函数。回调允许服务器猜得到吗反向调用 Web 页面中的代码。它也给了服务器一定程度的控制权当服务器完成请求之后会查看 XMLHttpRequest 对象特别是 onreadystatechange 属性。然后调用该属性指定的任何方法。之所以称为回调是因为服务器向网页发起调用无论网页本身在做什么。比方说可能在用户坐在椅子上手没有碰键盘的时候调用该方法但是也可能在用户输入、移动鼠标、滚动屏幕或者点击按钮时调用该方法。它并不关心用户在做什么。 这就是称之为异步的原因用户在一层上操作表单而在另一层上服务器响应请求并触发 onreadystatechange 属性指定的回调方法。因此需要像 清单 11 一样在代码中指定该方法。 清单 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. 回调方法的代码 script languagejavascript typetext/javascriptvar 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() {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);}function updatePage() {alert(Server is done!);}
/script 它仅仅发出一些简单的警告告诉您服务器什么时候完成了任务。在自己的网页中试验这些代码然后在浏览器中打开如果希望查看该例中的 XHTML请参阅 清单 8。输入电话号码然后离开该字段将看到一个弹出的警告窗口如 图 3 所示但是点击 OK 又出现了…… 图 3. 弹出警告的 Ajax 代码 根据浏览器的不同在表单停止弹出警告之前会看到两次、三次甚至四次警告。这是怎么回事呢原来我们还没有考虑 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);elsealert(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, );} elsealert(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 表单 结束本文之前我还要介绍 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 请求和以不同的格式发送数据。请开始编写代码吧一个月后我们再继续讨论。 参考资料 学习 您可以参阅本文在 developerWorks 全球站点上的 英文原文。掌握 Ajax第 1 部分: Ajax 简介developerWorks2005 年 12 月帮助您了解 Ajax这是一种构建网站的高生产率方法。本文中的参考资料列表都值得访问面向 Java 开发人员的 Ajax: 构建动态的 Java 应用程序developerWorks2005 年 9 月从 Java 的角度考察了 Ajax 服务器端。面向 Java 开发人员的 Ajax: Ajax 的 Java 对象序列化developerWorks2005 年 10 月从 Java 的角度分析了如何通过网络发送对象以及与 Ajax 交互。使用 AJAX 调用 SOAP Web 服务第 1 部分: 构建 Web 服务客户机developerWorks2005 年 10 月是关于集成 Ajax 和现有基于 SOAP 的 web 服务的相当高级的文章。Google GMail 是一个很好的例子说明了基于 Ajax 的应用程序如何改变 Web 的工作方式。Google Maps 是另一种基于 Google 的 Web 2.0 应用程序。Flickr 是一个很好的例子说明如何使用 Ajax 创建类似桌面的 Web 应用程序。Ajax: A New Approach to Web Applications 发明了 Ajax 一词所有 Ajax 开发人员都应该读一读。Why Ajax Matters Now 告诉您为什么 Ajax 很重要。如果使用的是 Microsoft 浏览器 Internet Explorer请访问 Microsoft Developer Networks XML Developer Center。请通过 在线文档 进一步了解 MSXMLMicrosoft XML 解析器。看一看响应中包含的所有 HTTP 状态码 列表。developerWorks Web Architecture 专区 专门发表各种基于 Web 的解决方案的文章。获得产品和技术 Elisabeth Freeman、Eric Freeman 和 Brett McLaughlin 合著的 Head Rush Ajax2005 年 2 月OReilly Media, Inc.以 Head First 风格将本文中所述的内容灌输到您的头脑中。Java and XML, Second EditionBrett McLaughlin2001 年 8 月OReilly Media, Inc.包括作者关于 XHTML 和 XML 转换的讨论。JavaScript: The Definitive GuideDavid Flanagan2001 年 11 月OReilly Media, Inc.详细介绍了如何使用 JavaScript、动态网页第二版增加了关于 Ajax 的两章。Head First HTML with CSS XHTMLElizabeth 和Eric Freeman2005 年 12 月OReilly Media, Inc.是学习 XHTML、CSS 以及如何将两者结合起来的完整参考。讨论 参与论坛讨论。developerWorks blogs加入 developerWorks 社区。 转载于:https://www.cnblogs.com/anruy/p/5038467.html