wml

转:Java 开发员AJAX 常见问题

Java 开发员AJAX 常见问题

作者: Greg Murray  译者:Cheng Fang

原文:https://blueprints.dev.java.net/ajax-faq.html

现在我们都有机会用AJAX 了,好多人发现这是个全新的世界。许多开发员会通过现有的框架来接触到AJAX ,或许你想深入钻研,扩充现有的功能。这些常见问题就是针对想在应用内加上AJAX 功能的开发员的。

  1. 我应该考虑用 AJAX吗?
  2. AJAX 能不能和Java一起用?
  3. 难道我的框架不提供AJAX吗?
  4. 该从哪里开始?
  5. 创建我自己的AJAX功能,我要知道些什么?
  6. 我真的需要学JavaScript吗?
  7. 有哪些 JavaScript 库和框架可以帮助Java开发员?
  8. 我应该使用哪种返回值类型, XML 或 text, JavaScript, 或 HTML?
  9. AJAX 用起来方便不方便?
  10. 我该怎样调试 JavaScript?
  11. 在AJAX调用中,我应该用HTTP GET还是 POST?
  12. 我该怎样提供国际化的AJAX交互?
  13. 我该如何处理并发的AJAX 请求?
  14. 在服务器端怎样和AJAX客户端交流?
  15. 针对 AJAX 客户,在哪里储存状态?
  16. 怎样提交表单或表单的一部分,但不刷新页面?
  17. 服务器端和客户端,谁有控制权?
  18. AJAX 在安全性方面有没有问题?
  19. 我什么时候用同步请求而不用异步请求?
  20. 那些 applet和plugin该怎么办?
  21. 该怎样处理向前和向后按钮?
  22. 用AJAX 怎样发送图像?
  23. 该怎样创建一个线程来实现AJAX轮询(polling)?

我应该考虑用 AJAX吗?

AJAX现在当然很红,但它不一定适合你。AJAX只能用在最新的浏览器上,暴露出许多浏览器兼容性问题,对许多人它还要求学会一些新技术。Alex Bosworth 写了篇不错的网志 AJAX Mistakes,在你全力投入AJAX以前值得一看。

另一方面,你可以实现丰富的,高度交互性的,快速响应的WEB应用,它们看起来真的很快。尽管人们还在争论基于AJAX的应用是不是真的更快, 用户已感到更直接了,因为当数据在后台交换的时候,用户就收到了积极反馈。如果你较早采用了AJAX,能够处理浏览器兼容性问题,而且愿意学习一些新技术,那么AJAX是适合你的。谨慎起见,你可以试着把应用的一小部分或者小组件转化成AJAX。我们都喜欢新技术,但要记住AJAX的目的是要改善而不是妨碍用户的体验。

AJAX 能不能和Java一起用?

当然。Java很适合AJAX!你可以用Java企业版服务器来生成AJAX 客户端页面并处理进来的请求,为AJAX 客户端管理服务器端的状态,并且把AJAX 客户端联接到企业资源。JavaServer Faces 组件模型非常适合于定义和使用AJAX组件。

难道我的框架不提供AJAX吗?

你可能已经受益于AJAX。许多现有的基于Java 的框架已经有一定的AJAX 交互,许多新的框架和组件正在被开发来更好地支持AJAX。这里我不想列出所有用AJAX 的Java框架,因为我怕会遗漏一些。但是你可以在这里找到一个不错的列单: www.ajaxpatterns.org/Java_Ajax_Frameworks.

如果你还没有选好一个框架,我建议你考虑使用JavaServer Faces 或者基于JavaServer Faces的框架。你可以用JavaServer Faces组件来抽象化处理许多细节:生成JavaScript, AJAX交互, 和DHTML处理,这样JSF开发员就可以更方便地使用AJAX,它们还可以作为插件装入支持JSF的IDE内,比如 Sun Java Studio Creator.

该从哪里开始?

如果你现在的框架不能满足你的用例,你想开发自己的AJAX组件和功能,我建议你先看一下这篇文章Asynchronous JavaScript Technology and XML (AJAX) With Java 2 Platform, Enterprise Edition。(译者注:中文版 在Java2平台企业版中应用异步 JavaScript技术和XML(AJAX)

如果你想看一个很基本的例子和源代码,这里有 Using AJAX with Java TechnologyBlueprints AJAX Home 有更完整的AJAX资源。

接下来,我建议你花些时间研究AJAX库和框架。如果你想自己写AJAX客户端脚本,最好不要再重复劳动了。

Dave Crane,Eric Pascarello和Darren James的AJAX in Action也不错。这本书有附录中讲学习 JavaScript,对Java开发员有帮助。

创建我自己的AJAX 功能,我要知道些什么?

如果你不想利用已有的AJAX组件,这里是一些需要注意的地方。

准备学习动态HTML (DHTML), AJAX的基础技术。DHTML让用户与网页间通过浏览器现时交互成为可能。DHTML结合了JavaScript,文档对象模型(DOM)和层叠样式表 (CSS).

  • JavaScript - JavaScript是个宽松类型的,基于对象的脚本语言。它是AJAX交互的关键,而且所有的主流浏览器都支持它。当页面中的一个事件发生时,例如,载入页面,鼠标点击,或表单元素上的按键,JavaScript就被调用了。
  • 文档对象模型(DOM) - 用来读取和更改结构化文档的应用编程接口。在大多数情况下DOM代表XML和HTML文档的结构。
  • 层叠样式表(CSS) - 让你定义页面的外观,例如:字体,颜色,大小,和定位。CSS让你清晰地分隔开内容和形式,并且可以用JavaScript来编程改变。

理解HTTP的请求/回应这一基本性质也很重要。如果你在配置XMLHttpRequest时忽略了GET和POST方法的区别,或者在处理回调时忽略了HTTP状态代码,你会碰到许多难题。

从某种意义上说,JavaScript是一种客户端的胶合体。JavaScript被用来创建XMLHttpRequest对象并触发异步调用。 JavaScript被用来解析返回的内容。JavaScript被用来分析返回的数据并处理返回的信息。用JavaScript可以通过DOM API往HTML里注入内容和改变CSS。

我真的需要学JavaScript吗?

一般来说,是的,如果你想为你的WEB应用开发新的AJAX功能。

另外一方面, JSF 组件和组件库能抽象化JavaScript,DOM和CSS的细节。这些组件能生成必要的工件(artifacts)来支持AJAX交互。可视的工具,象Java Studio Creator,也可以利用支持AJAX的JSF组件来创建应用,应用开发者就不用担心AJAX的许多细节了。如果你打算写自己的 JSF组件,或者想把组件间的事件串联在一起,你应该对JavaScript有个基本了解。你可以从你页面里的JavaScript调用一些客户端的JavaScript 库(在下面谈到)来抽象化测声器间的差异。 Object Hierarchy and Inheritance in JavaScript 是一个供Java开发员学习JavaScript对象的很好的参考。

有哪些JavaScript 库和框架可以帮助Java开发员?

已经有许多库和框架(而且许多还在涌现出来)能帮助我们抽象化这些讨厌的浏览器差异。三个不错的库是:The Dojo Toolkit, Prototype, and DWR.
  • The Dojo Toolkit 包含一些API和工具来支持开发富WEB应用。Dojo包含一个智能的包装系统,用户界面效果,拖放方法(Drag and Drop) API,小应用(widget)API,事件抽象,客户存储API,以及AJAX交互API。Dojo解决了一些常见的可用性(Usability)问题, 比如,处理浏览器导航问题包括察觉浏览器退后按钮,更改地址栏里的URL来收藏书签,当客户端不完全支持AJAX和JavaScript时妥善处理。Dojo就好比是JavaScript库中的一把瑞士军刀。 它在一个库里提供了最广泛的选择,而且能很好地支持新老浏览器。
  • Prototype 专注于通过JavaScript AJAX对象进行AJAX 交互,它包含了若干对象来做基本的工作,比如发出请求,更新部分文档,往文档里插入内容,以及定期更新部分文档。Prototype JavaScript库包含了一套JavaScript对象来代表AJAX请求,和一些效用函数来读取页面内的数据和修改DOM。 Script.aculo.usRico就是建立在Prototype之上并提供了用户界面效果,支持拖放效果,以及一些围绕JavaScript的不工具(widgets)。如果你想支持AJAX交互和一些基本的功能,Prototype是个很好的选择。如果你需要用户界面效果,Script.aculo.us和Rico是不错的。

  • Yahoo UI Library 是一个通过API来支持富客户端的效用库和一套小应用。这个效用库包括了支持跨浏览器的AJAX交互,动画,DOM脚本,拖放,以及跨浏览器事件。 Yahoo UI Library提供较好的文档和许多例子。

  • DWR (Dynamic Web Remoting) 是一个客户端和服务器端的框架,它专注于允许开发员实现从客户端JavaScript到J2EE WEB容器内的普通Java对象(Plain Old Java Object)之间的远程调用。在服务器端,DWR用一个Servlet来和Java对象交互,并返回Java对象或做成了对象的XML文档。 DWR安装使用方便,和其它Java技术配合较好。如果你想要一个整合性能良好,同时支持客户端和服务器的框架,那就用 DWR.

  • Zimbra 是个客户端和服务器的框架,它专注于支持消息(messaging),包括向使用JavaScript的客户端提供电子邮件服务。在它的工具包中有抽象化浏览器差异的UI API(同时也包括了许多内在的小应用),支持UI事件通信和客户与服务器之间通信的API,简化客户端JavaScript开发的效用类,抽象化了的 DOM API以简化跨浏览器操作,和一套网络API来帮助JavaScript客户端AJAX和SOAP通信。

有好多新的JavaScript库正在涌现出来,以上只是回顾了比较常见的库。选择最适合你需要的。尽管你最好用一个框架,当然也可以同时用多个。更详细的客户端框架列单,请看:Survey of AJAX/JavaScript Libraries.

我应该使用哪种返回值类型, XML 或 text, JavaScript, 或 HTML?

这要看情况。很清楚,AJAX里的X代表了XML,但是一些AJAX支持者马上也指出,AJAX本身并不排除使用其它种类做载荷(PAYLOAD),比如,JavaScript, HTML, 或是纯文本格式。

  • XML - Web Services和AJAX看起来天生般配。你可以用客户端的API来下载和解析来自REST一类Web Services的XML内容。(不过,要小心在有些基于SOAP的Web Services中载荷会变得又大又复杂,所以不适合AJAX技术)。
  • 纯文本格式 - 在种情况下,服务器产生的文本被注入文档中,或用客户端逻辑来评估。
  • JavaScript - 是纯文本格式的延伸,不过服务器端组件会传递JavaScript脚本的分段,包括JavaScript对象声明。你可以在客户端用JavaScript eval()函数来创建这些对象。JSON,一个基于 JavaScript对象的数据交换规范,就是依赖了这种技术。
  • HTML - 直接把服务器生成的HTML分段注入文档,这通常是一种很有效的AJAX方法。不过,要让服务器端的组件和客户端的显示内容保持一致会有点复杂。

网络聚合(Mashup) 这是一个时下流行的术语,它从离散的WEB SERVICES和其它在线API获取内容,结合在一起创建全新的WEB应用。 一个很好的网络聚合的例子就是housingmaps.com,它把craiglist.org 的住房广告和 maps.google.com的地图结合在一起。

AJAX用起来方便不方便?

通过AJAX交互和DHTML的途径来获取数据,动态更新页面,这在本质上是会大幅度地改变页面的外观和状态。用户可能会在任何时候用到浏览器的向前或退后按钮,书签收藏当前页面,从地址栏复制URL后通过电子邮件或聊天发给朋友,或者是打印页面。在设计AJAX应用时,你应该考虑在发生这些情况时你预期的结果是怎样:导航,书签收藏,打印,浏览器支持, 如下所述:

  • 导航- 向前,退后,刷新和书签收藏这些浏览器按钮被点击时,你应用设计预期的结果是什么?你虽然可以用手工地实现一些历史控制,但更简便的方法是用一些能提供历史和导航控制API的JavaScript框架,比如Dojo
  • 书签收藏和URL分享 - 许多用户想书签收藏或从地址栏里拷贝URL。Dojo 支持客户端书签收藏和修改URL。
  • 打印- 有些时候打印动态产生的页面会有问题。

开发员使用AJAX时其它考虑因素:

  • 浏览器支持 - 并不是所有的浏览器,或一个浏览器的所有版本都支持所有的AJAX或DHTML功能。quirksmode.org 列举了浏览器支持情况和可能的变通方法。
  • JavaScript被关闭 - 你还应该考虑如果用户关闭使用JavaScript,你该怎么办。另外,有些用户的浏览器上因为有些原因不能支持JavaScript和CSS。
  • 等待时间(Latency) - 在你的设计中应该考虑到等待时间。应用在运行时应该比部署时更加响应迅速。同时要考虑到发出多个请求时,返回的次序是没有保障的。详情请看AJAX Latency problems: myth or reality?
  • 可访问性 - 确保你的网站能让有残障的人访问,这不光是一个高尚的目标,在很多地区也是法律。有许多优秀的支撑技术能帮助他们使用网络,尽管他们有视觉,听觉,体力,语言,认知和神经方面的残障。有一点前瞻性,理解这方面的丰富文档和最好实践,你就能确保你的应用符合这些支撑技术的要求。

降解效果(Degradability)这个术语描述了WEB应用用于适应广泛的浏览器功能的一系列技巧。许多AJAX库有内置的自动降解方式。如果你要写自己的AJAX功能,考虑采纳一些标准组织,比如World Wide Web Conrsoritum (W3C), 和草根运动,比如Web Standards和其它人的最佳实践。这样你的应用在不支持AJAX的浏览器上仍然能运行,虽然它失去了一些很抢眼的效果。

记住不要只是为了显得酷而用AJAX。你打造WEB应用是为了给人用的。如果和他们的浏览器上不兼容,用户就不会用你的应用。

我该怎样调试 JavaScript?

没有很多调试器能同时支持客户端和服务器端调试。我肯定随着AJAX的普及,这种情况会改变。我现在分开调试客户端和服务器。以下是一些关于常见浏览器上的客户端调试器的情况:

  • Firefox/Mozilla/Netscape - 在一个内置的调试器Venkman很有帮助。我喜欢先在 Firefox开发应用,然后再到其它浏览器上去试。
  • Safari - 有一个调试器,你需要先开户。详情请看Safari FAQ
  • Internet Explorer - MSDN Documentation上有关于调试JavaScript的文档。Internet Explorer developer toolbar可能也有帮助。

除了调试器能帮忙,还有一种常用的方法叫“对话框调试(Alert Debugging)”。在这种情况下你加入"alert()"函数调用,就好比在JAVA中用System.out.println一样。尽管是一个很小的窍门,对大部分情况都管用。有些框架,象Dojo,提供 API来追踪调试语句。

在AJAX调用中,我应该用HTTP GET还是 POST?

如果相对于一个待定的URL的数据一会改变,那么AJAX请求应该用HTTP GET方法。如果服务器会更新状态,那么就应该用HTTP POST方法。这和HTTP idempotency recommendations的要求是一致的,也是大家为创造一个统一的WEB应用设计而高度推荐的做法。

我该怎样提供国际化的AJAX交互?

不能认为用了XML, 你就能以AJAX请求发送和获取区域化的内容。要提供国际化的AJAX组件,你需要做以下这些要求:

  • 把页面字符集设成目标语言支持的编码。你趋向于使用UTF-8,因为它涵盖了在部分语言。以下一个HTML/JSP页面的meta声明设置了 content type:
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  • 在页面内JavaScript确保每个发往服务器的参数都被编码。JavaScript提供了一个escape()函数来返回统一码(UNICODE)转义字符串,这样区域化的文本就以十六进制的格式出现。更多关于JavaScript编码的信息,请看Comparing escape(), encodeURI(), and encodeURIComponent().
  • 服务器端组件用HttpServletRequest.setCharacterEncoding()方法设置字符编码。这必须发生在用 HttpServletRequest.getParameter()方法读取区域化参数以前。如果是UTF-8,那就应该是 request.setCharactherEncoding("UTF-8");.

返回AJAX回应的服务器端组件需要把回应的编码设成和该页面一样的编码。

    response.setContentType("text/xml;charset=;UTF-8");
response.getWriter().write("<response>invalid</response>");

关于在Java企业版上使用AJAX,更多资料请看AJAX and Internationalization,开发多种语言应用,请看Developing Multilingual Web Applications Using JavaServer Pages Technology.

我该如何处理并发的AJAX 请求?

通过JavaScript你可以同时处理多个AJAX 请求。为了确保妥善的后处理,我建议使用JavaScript闭包(JavaScript Closures)。下面这个例子显示了一个XMLHttpRequest 被抽象化为JavaScript对象AJAXInteraction。传进的参数是要调用的URL和处理结束后要调用的函数。

function AJAXInteraction(url, callback) {

var req = init();
req.onreadystatechange = processRequest;

function init() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}

function processRequest () {
if (req.readyState == 4) {
if (req.status == 200) {
if (callback) callback(req.responseXML);
}
}
}

this.doGet = function() {
req.open("GET", url, true);
req.send(null);
}

this.doPost = function(body) {
req.open("POST", url, true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.send(body);
}
}

function makeRequest() {
var ai = new AJAXInteraction("processme", function() { alert("Doing Post Process");});
ai.doGet();
}

在上例中,makeRequest()函数创建了一个AJAXInteraction,传入两个参数:要调用的URL“processme”和一个内联函数。这个内联函数会弹出对话框来显示信息"Doing Post Process"。调用ai.doGet()就启动了AJAX 互动,当映射到URL "processme" 的服务器端组件返回一个文档,这个文档再被传给创建这个AJAXInteraction时指定的回调函数。

使用这样的闭包能确保对应于一特定的AJAX交互的回调函数能被正确调用。当你使用多个闭包对象来做XmlHttpRequests时仍需小心,因为在任何一特定时刻都只有有限的套接字(SOCKET)用来发出请求。因为只能有有限数目的并行请求,Internet Explorer只允许任何时刻最多两个并行AJAX请求 。其它浏览器可能会允许更多,但一般是三个到五个之间。你也可以用来管理AJAXInteraction对象。

有一点要注意,当从客户端发出多个AJAX请求时,它们的返回值没有特定的次序。在回调函数中使用闭包能确保这些信赖能被正确处理。

这个讨论很有帮助Ajaxian Fire and Forget Pattern

在服务器端怎样和AJAX客户端交流?


对于返回值类型XML,"Content-Type" 要设成"text/xml"。在SERVLET里可以用 HttpServletReqponse.setContentType()。许多XMLHttpRequest 实现如果发现"Content-Type"已经设了会报错。一面的代码显示了如何设"Content-Type":

    response.setContentType("text/xml");
response.getWriter().write("<response>invalid</response>");

你可能要考虑是不是要设缓存标头。在些时候,比如自动补全,你可能要通知代理服务器和浏览器不要缓存结果。

    response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
response.getWriter().write("<response>invalid</response>");
开发员注意:如果这个标头没有设,Internet Explorer 对于HTTP GET方法的响应会自动用缓存的结果。这可能会引起一些问题。所以在开发的时候你可能要设这个标头。

针对AJAX客户,在哪里储存状态?

和任何基于浏览器的WEB应用一样,你有以下这些选择:

  • 在客户端使用cookie - 大小有限(一般是每个域名20个cookie ,每个cookie 4KB,总共80KB)。除非加密,否则不安全。加密是困难的,但用JavaScript也不是不可能。
  • 在客户端页面中 - 这种方法安全,但用起来困难,容易出问题。我的一篇网志有更详细的讨论:Storing State on the Client
  • 在客户端文件系统内 - 如果浏览器已有权限写往本地文件系统,这是可行的。取决于你的用例,这可能也就够了,但也需谨慎。
  • 在服务器端 - 这和传统模式最想象:客户的状态保存在服务器上。如何保持数据一致会是个问题,所以我们针对这设计了这样一种方案Refreshing Data。当我们把更多的数据处理移往客户端时,就需要重新评估在哪里储存状态。

怎样提交表单或表单的一部分,但不刷新页面?

当建立表单的时候,要确保"form"元素的"onSubmit"属性设成一个返回false的JavaScript函数。

  <form onSubmit="doAJAXSubmit();return false;" >
<input type="text" id="tf1" />
<input type="submit" id="submit1" value="Update"/>
</>

用同样的方法,你也可以联接函数和表单按钮,从而来提交表单:

  <form onSubmit="doAJAXSubmit();return false;" >
<input type="text" id="tf1" />
<input type="button" id="button1" onClick="doAJAXSubmit()" value="Update"/>
</>

注意:表单上的"onSubmit"属性已被设置。如果用户在文本输入框中按了回车,表单也会被提交。所以你要处理这种情况。

当更新页面时,我建议你等到确保AJAX已经顺利更新了表单数据后再更新页面数据。否则,数据可能没有适当更新,用户却不知道。我喜欢在做部分更新时给用户一个提醒信息,等AJAX交互顺利结束后,再更新页面。

服务器端和客户端,谁有控制权?

这要看情况而定。对于AJAX来说,答案在两者中间。服务器端组件可实施更强的中央控制,或者服务器端和客户端一起来控制。

  • 中央化的服务器端控制器 - 当你用一个更中央化的控制器时,关键是要确保客户端页面的数据和服务器端保持一致。有些应用在服务器保持状态,并把所有的更新通过一个简单的 JavaScript控制器推送到客户端的DOM。
  • 客户端和服务器端的控制器 - 这种设计会用JavaScript来做所有与表现有关的控制,事件处理,页面修改,并在客户端渲染显示业务数据。服务器端负责的事情包括业务逻辑,和把更新后的业务数据推送给客户。在这种情况下,服务器除了发送往客户的最初页面以外,并不熟悉表现层的情况,

在有些用例中,整个AJAX应用只有一个页面。但要记住,如果你选用了这种设计,务必考虑到浏览器导航和书签收藏。

取决于你想实现什么,这两种方法都可以采用。我趋向于让把控制分布到服务器端和客户端。

AJAX在安全性方面有没有问题?

用户通过查看页面源代码就可以看见JavaScript的源代码。没有用户赋予的权限,JavaScript不能访问本地文件系统。AJAX只能与提供该页面下载的服务器上的组件交互。代理模式可用来与外部服务交互。

你要小心有要暴露你应用的模型,因为有些恶意用户会用逆反工程危及你服务器的组件。就象其它WEB应用一样,当交换敏感信息的时候,考虑使用 HTTPS来保护连接。

我什么时候用同步请求而不用异步请求?

问得好。叫它AJAX是有道理的。一个同步请求会堵塞页面的事件处理,我还没发现很多同步比异步好的用例。

那些applet和plugin该怎么办?

不要急于抛弃基于 applet 和 plugin 的应用。尽管AJAX 和 DHTML 能够实现拖放效果和其它高级用户界面功能,但它们仍然有局限性,特别是在浏览器支持方面。Plugin 和 applet 已经存在了一段时间,而且一直都能实现类似于AJAX 请求的功能。Applet 提供了开发员所需要的一系列优秀的用户界面组件和API。

许多人不愿意用 applet 或者 plugin,因为它们启动的时候需要等一段时间,而且无法保证应用需要的JVM plugin 版本已被安装。Plugin 和 applet 可能在操纵 DOM 上有欠缺。如果你在一个统一的环境下,或者你可以肯定你的应用能找到一个特定版本的JVM plugin(比如在一个公司内部环境),那么 plugin 或 applet 就一失为一个良好的解决方案。

还有一种选择是把AJAX和 applet 或  plugin 混合起来使用。Flickr 就是这样,一方面用 AJAX 交互或者 DHTML 来标识图形和与用户交流,另一方面用一个 plugin 来管理照片,从面提供了极好的用户体验。如果服务器端组件设计得好的话,它们可以同时与这两种客户会话。

该怎样处理向前和向后按钮?

你可以开发自己的方案在应用中追踪当前的状态,但是我建议你还是把这种任务留给专家来做。Dojo 以不待定于浏览器的方式来处理导航问题,如下所示:

function updateOnServer(oldId, oldValue, itemId, itemValue) {
var bindArgs = {
url: "faces/ajax-dlabel-update",
method: "post",
content: {"component-id": itemId, "component-value": itemValue},
mimetype: "text/xml",
load: function(type, data) {
processUpdateResponse(data);
},
backButton: function() {
alert("old itemid was " + oldId);
},
forwardButton: function(){
alert("forward we must go!");
}
};
dojo.io.bind(bindArgs);
}

上面的例子用到了 dojo.io.bind() 来更改服务端的一个值,dojo.io.bind()  还用到了一个函数来负责处理浏览器向后按钮事件。这样作为一个开发员你就可以在上例中恢复以前的值(oldValue),或者采取其它合适的行动。开发员不用关注怎样察觉到浏览器按钮事件这些底层细节,因为Dojo已经处理掉了。

AJAX: How to Handle Bookmarks and Back Buttons 这篇文章详细介绍了这个问题,并提供了一个专门注重向前和后退问题的 JavaScript 库。

用AJAX怎样发送图像?


当类似 Google Maps 的应用使用AJAX时,它们看上去似乎在发送图像,事实上,针对AJAX请求,图像URL作为响应被发送回去,然后通过DHTML来设置显示图像。

在这个例子中,AJAX 交互返回了一个XML 文档,然后填充 category 一栏。

<categories>
<category>
<cat-id>1</cat-id>
<name>Books</name>
<description>Fun to read</description>
<image-url>books_icon.gif</image-url>
</category>
<category>
<cat-id>2</cat-id>
<name>Electronics</name>
<description>Must have gadgets</description>
<image-url>electronics.gif</image-url>
</category>
</categories>

请注意image-url元素包含了代表category元素的图像的URL。AJAX交互的回调函数会解析作为响应的 XML文档,并针对包括在XML响应文档中的每个category调用addCategory函数。addCategory函数在页面主体中查找一个叫"categoryTable" 的表格行元素,把以上的图像作为新的一行加进去。

<scrip type="text/javascript" >

...

function addCategory(id, name, imageSrc) {

var categoryTable = document.getElementById("categoryTable");
var row = document.createElement("tr");
var catCell = document.createElement("td");
var img = document.createElement("img");
img.src = ("images\\" + imageSrc);
var link = document.createElement("a");
link.className ="category";
link.appendChild(document.createTextNode(name));
link.setAttribute("onclick", "catalog?command=category&catid=" + id);
catCell.appendChild(img);
catCell.appendChild(link);
row.appendChild(catCell);
categoryTable.appendChild(row);
}
</script>

...

<table>
<tr>
<td width="300" bgoclor="lightGray">
<table id="categoryTable" border="0" cellpadding="0"></table>
</td>
<td id="body" width="100%">Body Here</td>
</tr>
</table>

请注意到image source元素被设成了图像的来源。接下来当img元素被加到categoryTable时,页面会发出一个HTTP请求来载入位于"images/books_icon.gif" 或 "images/electronic_icon.gif" 的图像。

该怎样创建一个线程来实现AJAX轮询(polling)?

JavaScript 没有线程。当页面叫发生某种事件时,比如页面载入,鼠标点击,或表单元素获取输入焦点, JavaScript 的函数会被调用。你可以用
setTimeout 来建立一个定时器,这个函数用到两个参数:另外一个函数的名字和毫秒数。这样你就可以循环调用同一个函数,如下所示:

function checkForMessage() {
// start AJAX interaction with processCallback as the callback function
}

// callback for the request
function processCallback() {

// do post processing

setTimeout("checkForMessage()", 10000);
}

请注意checkForMessage会一直无限制循环下去。根据你页面的活动或用例,你可能需要改变一下间隔时间。你可能需要针对处理AJAX响应的某些条件来安排逻辑中断循环。

posted on 2006-07-04 13:53 wml 阅读(673) 评论(0)  编辑  收藏 所属分类: AJAX