轉:Java 開發員AJAX 常見問題
Java 開發員AJAX 常見問題
作者: Greg Murray? 譯者:Cheng Fang
原文:https://blueprints.dev.java.net/ajax-faq.html
現在我們都有機會用AJAX 了,好多人發現這是個全新的世界。許多開發員會通過現有的框架來接觸到AJAX ,或許你想深入鉆研,擴充現有的功能。這些常見問題就是針對想在應用內加上AJAX 功能的開發員的。
- 我應該考慮用 AJAX嗎?
- AJAX 能不能和Java一起用?
- 難道我的框架不提供AJAX嗎?
- 該從哪里開始?
- 創建我自己的AJAX功能,我要知道些什么?
- 我真的需要學JavaScript嗎?
- 有哪些 JavaScript 庫和框架可以幫助Java開發員?
- 我應該使用哪種返回值類型, XML 或 text, JavaScript, 或 HTML?
- AJAX 用起來方便不方便?
- 我該怎樣調試 JavaScript?
- 在AJAX調用中,我應該用HTTP GET還是 POST?
- 我該怎樣提供國際化的AJAX交互?
- 我該如何處理并發的AJAX 請求?
- 在服務器端怎樣和AJAX客戶端交流?
- 針對 AJAX 客戶,在哪里儲存狀態?
- 怎樣提交表單或表單的一部分,但不刷新頁面?
- 服務器端和客戶端,誰有控制權?
- AJAX 在安全性方面有沒有問題?
- 我什么時候用同步請求而不用異步請求?
- 那些 applet和plugin該怎么辦?
- 該怎樣處理向前和向后按鈕?
- 用AJAX 怎樣發送圖像?
- 該怎樣創建一個線程來實現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 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:
<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");開發員注意:如果這個標頭沒有設,Internet Explorer 對于HTTP GET方法的響應會自動用緩存的結果。這可能會引起一些問題。所以在開發的時候你可能要設這個標頭。
response.setHeader("Cache-Control", "no-cache");
response.getWriter().write("<response>invalid</response>");
針對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 閱讀(690) 評論(0) 編輯 收藏 所屬分類: AJAX