Java 开发员AJAX 常见问题
2010年09月08日
我应该考虑用 AJAX吗?
AJAX现在当然很红,但它不一定适合你。AJAX只能用在最新的浏览器上,暴露出许多浏览器兼容性问题,对许多人它还要求学会一些新技术。Alex Bosworth 写了篇不错的网志 AJAX Mistakes,在你全力投入AJAX以前值得一看。
另一方面,你可以实现丰富的,高度交互性的,快速响应的WEB应用,它们看起来真的很快。尽管人们还在争论基于AJAX的应用是不是真的更快, 用户已感到更直接了,因为当数据在后台交换的时候,用户就收到了积极反馈。如果你较早采用了AJAX,能够处理浏览器兼容性问题,而且愿意学习一些新技术,那么AJAX是适合你的。谨慎起见,你可以试着把应用的一小部分或者小组件转化成AJAX。我们都喜欢新技术,但要记住AJAX的目的是要改善而不是妨碍用户的体验。
AJAX 能不能和Java一起用?
当然。Java很适合AJAX!你可以用Java企业版服务器来生成AJAX 客户端页面并处理进来的请求,为AJAX 客户端管理服务器端的状态,并且把AJAX 客户端联接到企业资源。JavaServe* **ces 组件模型非常适合于定义和使用AJAX组件。
难道我的框架不提供AJAX吗?
你可能已经受益于AJAX。许多现有的基于Java 的框架已经有一定的AJAX 交互,许多新的框架和组件正在被开发来更好地支持AJAX。这里我不想列出所有用AJAX 的Java框架,因为我怕会遗漏一些。但是你可以在这里找到一个不错的列单: www.ajaxpatterns.org/Java_Ajax_Frameworks.
如果你还没有选好一个框架,我建议你考虑使用JavaServe* **ces 或者基于JavaServe* **ces的框架。你可以用JavaServe* **ces组件来抽象化处理许多细节:生成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 Technology。 Blueprints 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.us和Rico就是建立在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:
在页面内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("invalid");
关于在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.respon***ML); } } } 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("invalid");
你可能要考虑是不是要设缓存标头。在些时候,比如自动补全,你可能要通知代理服务器和浏览器不要缓存结果。
response.setContentType("text/xml"); response.setHeader("Cache-Control", "no-cache"); response.getWriter().write("invalid");
开发员注意:如果这个标头没有设,Internet Explorer 对于HTTP GET方法的响应会自动用缓存的结果。这可能会引起一些问题。所以在开发的时候你可能要设这个标头。
针对AJAX客户,在哪里储存状态?
和任何基于浏览器的WEB应用一样,你有以下这些选择:
在客户端使用cookie - 大小有限(一般是每个域名20个cookie ,每个cookie 4KB,总共80KB)。除非加密,否则不安全。加密是困难的,但用JavaScript也不是不可能。
在客户端页面中 - 这种方法安全,但用起来困难,容易出问题。我的一篇网志有更详细的讨论:Storing State on the Client。
在客户端文件系统内 - 如果浏览器已有权限写往本地文件系统,这是可行的。取决于你的用例,这可能也就够了,但也需谨慎。
在服务器端 - 这和传统模式最想象:客户的状态保存在服务器上。如何保持数据一致会是个问题,所以我们针对这设计了这样一种方案Refreshing Data。当我们把更多的数据处理移往客户端时,就需要重新评估在哪里储存状态。
怎样提交表单或表单的一部分,但不刷新页面?
当建立表单的时候,要确保"form"元素的"onSubmit"属性设成一个返回false的JavaScript函数。
用同样的方法,你也可以联接函数和表单按钮,从而来提交表单:
注意:表单上的"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 一栏。
1 Books Fun to read books_icon.gif 2 Electronics Must have gadgets electronics.gif
请注意image-url元素包含了代表category元素的图像的URL。AJAX交互的回调函数会解析作为响应的 XML文档,并针对包括在XML响应文档中的每个category调用addCategory函数。 addCategory函数在页面主体中查找一个叫"categoryTable" 的表格行元素,把以上的图像作为新的一行加进去。
...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);}... Body Here
请注意到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 requestfunction processCallback() { // do post processing setTimeout("checkForMessage()", 10000);}
请注意checkForMessage会一直无限制循环下去。根据你页面的活动或用例,你可能需要改变一下间隔时间。你可能需要针对处理AJAX响应的某些条件来安排逻辑中断循环。