版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
相當不錯的Ajax教程相當不錯的Ajax教程相當不錯的Ajax教程V:1.0精細整理,僅供參考相當不錯的Ajax教程日期:20xx年X月掌握Ajax第1部分:Ajax簡介理解Ajax及其工作原理,構(gòu)建網(wǎng)站的一種有效方法級別:初級BrettMcLaughlin,作家,編輯,O'ReillyandAssociates2006年1月04日Ajax由HTML、javascript技術(shù)、DHTML和DOM組成,這一杰出的方法可以將笨拙的Web界面轉(zhuǎn)化成交互性的Ajax應(yīng)用程序。本文的作者是一位Ajax專家,他演示了這些技術(shù)如何協(xié)同工作——從總體概述到細節(jié)的討論——使高效的Web開發(fā)成為現(xiàn)實。他還揭開了Ajax核心概念的神秘面紗,包括XMLHttpRequest對象。五年前,如果不知道XML,您就是一只無人重視的丑小鴨。十八個月前,Ruby成了關(guān)注的中心,不知道Ruby的程序員只能坐冷板凳了。今天,如果想跟上最新的技術(shù)時尚,那您的目標就是Ajax。但是,Ajax不僅僅是一種時尚,它是一種構(gòu)建網(wǎng)站的強大方法,而且不像學(xué)習(xí)一種全新的語言那樣困難。但在詳細探討Ajax是什么之前,先讓我們花幾分鐘了解Ajax做什么。目前,編寫應(yīng)用程序時有兩種基本的選擇:桌面應(yīng)用程序Web應(yīng)用程序兩者是類似的,桌面應(yīng)用程序通常以CD為介質(zhì)(有時候可從網(wǎng)站下載)并完全安裝到您的計算機上。桌面應(yīng)用程序可能使用互聯(lián)網(wǎng)下載更新,但運行這些應(yīng)用程序的代碼在桌面計算機上。Web應(yīng)用程序運行在某處的Web服務(wù)器上——毫不奇怪,要通過Web瀏覽器訪問這種應(yīng)用程序。不過,比這些應(yīng)用程序的運行代碼放在何處更重要的是,應(yīng)用程序如何運轉(zhuǎn)以及如何與其進行交互。桌面應(yīng)用程序一般很快(就在您的計算機上運行,不用等待互聯(lián)網(wǎng)連接),具有漂亮的用戶界面(通常和操作系統(tǒng)有關(guān))和非凡的動態(tài)性??梢詥螕簟⑦x擇、輸入、打開菜單和子菜單、到處巡游,基本上不需要等待。另一方面,Web應(yīng)用程序是最新的潮流,它們提供了在桌面上不能實現(xiàn)的服務(wù)(比如和eBay)。但是,伴隨著Web的強大而出現(xiàn)的是等待,等待服務(wù)器響應(yīng),等待屏幕刷新,等待請求返回和生成新的頁面。顯然這樣說過于簡略了,但基本的概念就是如此。您可能已經(jīng)猜到,Ajax嘗試建立桌面應(yīng)用程序的功能和交互性,與不斷更新的Web應(yīng)用程序之間的橋梁??梢允褂孟褡烂鎽?yīng)用程序中常見的動態(tài)用戶界面和漂亮的控件,不過是在Web應(yīng)用程序中。還等什么呢我們來看看Ajax如何將笨拙的Web界面轉(zhuǎn)化成能迅速響應(yīng)的Ajax應(yīng)用程序吧。老技術(shù),新技巧在談到Ajax時,實際上涉及到多種技術(shù),要靈活地運用它必須深入了解這些不同的技術(shù)(本系列的頭幾篇文章將分別討論這些技術(shù))。好消息是您可能已經(jīng)非常熟悉其中的大部分技術(shù),更好的是這些技術(shù)都很容易學(xué)習(xí),并不像完整的編程語言(如Java或Ruby)那樣困難。Ajax的定義順便說一下,Ajax是AsynchronousjavascriptandXML(以及DHTML等)的縮寫。這個短語是AdaptivePath的JesseJamesGarrett發(fā)明的(請參閱參考資料),按照Jesse的解釋,這不是個首字母縮寫詞。下面是Ajax應(yīng)用程序所用到的基本技術(shù):HTML用于建立Web表單并確定應(yīng)用程序其他部分使用的字段。javascript代碼是運行Ajax應(yīng)用程序的核心代碼,幫助改進與服務(wù)器應(yīng)用程序的通信。DHTML或DynamicHTML,用于動態(tài)更新表單。我們將使用div、span和其他動態(tài)HTML元素來標記HTML。文檔對象模型DOM用于(通過javascript代碼)處理HTML結(jié)構(gòu)和(某些情況下)服務(wù)器返回的XML。我們來進一步分析這些技術(shù)的職責。以后的文章中我將深入討論這些技術(shù),目前只要熟悉這些組件和技術(shù)就可以了。對這些代碼越熟悉,就越容易從對這些技術(shù)的零散了解轉(zhuǎn)變到真正把握這些技術(shù)(同時也真正打開了Web應(yīng)用程序開發(fā)的大門)。XMLHttpRequest對象要了解的一個對象可能對您來說也是最陌生的,即XMLHttpRequest。這是一個javascript對象,創(chuàng)建該對象很簡單,如清單1所示。清單1.創(chuàng)建新的XMLHttpRequest對象<scriptlanguage="javascript"type="text/javascript">varxmlHttp=newXMLHttpRequest();</script>下一期文章中將進一步討論這個對象,現(xiàn)在要知道這是處理所有服務(wù)器通信的對象。繼續(xù)閱讀之前,先停下來想一想:通過XMLHttpRequest對象與服務(wù)器進行對話的是javascript技術(shù)。這不是一般的應(yīng)用程序流,這恰恰是Ajax的強大功能的來源。在一般的Web應(yīng)用程序中,用戶填寫表單字段并單擊Submit按鈕。然后整個表單發(fā)送到服務(wù)器,服務(wù)器將它轉(zhuǎn)發(fā)給處理表單的腳本(通常是PHP或Java,也可能是CGI進程或者類似的東西),腳本執(zhí)行完成后再發(fā)送回全新的頁面。該頁面可能是帶有已經(jīng)填充某些數(shù)據(jù)的新表單的HTML,也可能是確認頁面,或者是具有根據(jù)原來表單中輸入數(shù)據(jù)選擇的某些選項的頁面。當然,在服務(wù)器上的腳本或程序處理和返回新表單時用戶必須等待。屏幕變成一片空白,等到服務(wù)器返回數(shù)據(jù)后再重新繪制。這就是交互性差的原因,用戶得不到立即反饋,因此感覺不同于桌面應(yīng)用程序。Ajax基本上就是把JavaScript技術(shù)和XMLHttpRequest對象放在Web表單和服務(wù)器之間。當用戶填寫表單時,數(shù)據(jù)發(fā)送給一些javascript代碼而不是直接發(fā)送給服務(wù)器。相反,javascript代碼捕獲表單數(shù)據(jù)并向服務(wù)器發(fā)送請求。同時用戶屏幕上的表單也不會閃爍、消失或延遲。換句話說,javascript代碼在幕后發(fā)送請求,用戶甚至不知道請求的發(fā)出。更好的是,請求是異步發(fā)送的,就是說javascript代碼(和用戶)不用等待服務(wù)器的響應(yīng)。因此用戶可以繼續(xù)輸入數(shù)據(jù)、滾動屏幕和使用應(yīng)用程序。然后,服務(wù)器將數(shù)據(jù)返回javascript代碼(仍然在Web表單中),后者決定如何處理這些數(shù)據(jù)。它可以迅速更新表單數(shù)據(jù),讓人感覺應(yīng)用程序是立即完成的,表單沒有提交或刷新而用戶得到了新數(shù)據(jù)。javascript代碼甚至可以對收到的數(shù)據(jù)執(zhí)行某種計算,再發(fā)送另一個請求,完全不需要用戶干預(yù)!這就是XMLHttpRequest的強大之處。它可以根據(jù)需要自行與服務(wù)器進行交互,用戶甚至可以完全不知道幕后發(fā)生的一切。結(jié)果就是類似于桌面應(yīng)用程序的動態(tài)、快速響應(yīng)、高交互性的體驗,但是背后又擁有互聯(lián)網(wǎng)的全部強大力量。加入一些javascript得到XMLHttpRequest的句柄后,其他的javascript代碼就非常簡單了。事實上,我們將使用javascript代碼完成非?;镜娜蝿?wù):獲取表單數(shù)據(jù):javascript代碼很容易從HTML表單中抽取數(shù)據(jù)并發(fā)送到服務(wù)器。修改表單上的數(shù)據(jù):更新表單也很簡單,從設(shè)置字段值到迅速替換圖像。解析HTML和XML:使用javascript代碼操縱DOM(請參閱下一節(jié)),處理HTML表單服務(wù)器返回的XML數(shù)據(jù)的結(jié)構(gòu)。對于前兩點,需要非常熟悉getElementById()方法,如清單2所示。清單2.用javascript代碼捕獲和設(shè)置字段值alue;alue=response[0];("address").value=response[1];這里沒有特別需要注意的地方,真是好極了!您應(yīng)該認識到這里并沒有非常復(fù)雜的東西。只要掌握了XMLHttpRequest,Ajax應(yīng)用程序的其他部分就是如清單2所示的簡單javascript代碼了,混合有少量的HTML。同時,還要用一點兒DOM,我們就來看看吧。以DOM結(jié)束最后還有DOM,即文檔對象模型。可能對有些讀者來說DOM有點兒令人生畏,HTML設(shè)計者很少使用它,即使javascript程序員也不大用到它,除非要完成某項高端編程任務(wù)。大量使用DOM的是復(fù)雜的Java和C/C++程序,這可能就是DOM被認為難以學(xué)習(xí)的原因。幸運的是,在javascript技術(shù)中使用DOM很容易,也非常直觀?,F(xiàn)在,按照常規(guī)也許應(yīng)該說明如何使用DOM,或者至少要給出一些示例代碼,但這樣做也可能誤導(dǎo)您。即使不理會DOM,仍然能深入地探討Ajax,這也是我準備采用的方法。以后的文章將再次討論DOM,現(xiàn)在只要知道可能需要DOM就可以了。當需要在javascript代碼和服務(wù)器之間傳遞XML和改變HTML表單的時候,我們再深入研究DOM。沒有它也能做一些有趣的工作,因此現(xiàn)在就把DOM放到一邊吧。獲取Request對象有了上面的基礎(chǔ)知識后,我們來看看一些具體的例子。XMLHttpRequest是Ajax應(yīng)用程序的核心,而且對很多讀者來說可能還比較陌生,我們就從這里開始吧。從清單1可以看出,創(chuàng)建和使用這個對象非常簡單,不是嗎等一等。還記得幾年前的那些討厭的瀏覽器戰(zhàn)爭嗎沒有一樣?xùn)|西在不同的瀏覽器上得到同樣的結(jié)果。不管您是否相信,這些戰(zhàn)爭仍然在繼續(xù),雖然規(guī)模較小。但令人奇怪的是,XMLHttpRequest成了這場戰(zhàn)爭的犧牲品之一。因此獲得XMLHttpRequest對象可能需要采用不同的方法。下面我將詳細地進行解釋。使用Microsoft瀏覽器Microsoft瀏覽器InternetExplorer使用MSXML解析器處理XML(可以通過參考資料進一步了解MSXML)。因此如果編寫的Ajax應(yīng)用程序要和InternetExplorer打交道,那么必須用一種特殊的方式創(chuàng)建對象。但并不是這么簡單。根據(jù)InternetExplorer中安裝的javascript技術(shù)版本不同,MSXML實際上有兩種不同的版本,因此必須對這兩種情況分別編寫代碼。請參閱清單3,其中的代碼在Microsoft瀏覽器上創(chuàng)建了一個XMLHttpRequest。清單3.在Microsoft瀏覽器上創(chuàng)建XMLHttpRequest對象varxmlHttp=false;try{xmlHttp=newActiveXObject("");}catch(e){try{xmlHttp=newActiveXObject("");}catch(e2){xmlHttp=false;}}您對這些代碼可能還不完全理解,但沒有關(guān)系。當本系列文章結(jié)束的時候,您將對javascript編程、錯誤處理、條件編譯等有更深的了解。現(xiàn)在只要牢牢記住其中的兩行代碼:xmlHttp=newActiveXObject("");和xmlHttp=newActiveXObject("");。這兩行代碼基本上就是嘗試使用一個版本的MSXML創(chuàng)建對象,如果失敗則使用另一個版本創(chuàng)建該對象。不錯吧如果都不成功,則將xmlHttp變量設(shè)為false,告訴您的代碼出現(xiàn)了問題。如果出現(xiàn)這種情況,可能是因為安裝了非Microsoft瀏覽器,需要使用不同的代碼。處理Mozilla和非Microsoft瀏覽器如果選擇的瀏覽器不是InternetExplorer,或者為非Microsoft瀏覽器編寫代碼,就需要使用不同的代碼。事實上就是清單1所示的一行簡單代碼:varxmlHttp=newXMLHttpRequestobject;。這行簡單得多的代碼在Mozilla、Firefox、Safari、Opera以及基本上所有以任何形式或方式支持Ajax的非Microsoft瀏覽器中,創(chuàng)建了XMLHttpRequest對象。結(jié)合起來關(guān)鍵是要支持所有瀏覽器。誰愿意編寫一個只能用于InternetExplorer或者非Microsoft瀏覽器的應(yīng)用程序呢或者更糟,要編寫一個應(yīng)用程序兩次當然不!因此代碼要同時支持InternetExplorer和非Microsoft瀏覽器。清單4顯示了這樣的代碼。清單4.以支持多種瀏覽器的方式創(chuàng)建XMLHttpRequest對象/*CreateanewXMLHttpRequestobjecttotalktotheWebserver*/varxmlHttp=false;/*@cc_on@*//*@if(@_jscript_version>=5)try{xmlHttp=newActiveXObject("");}catch(e){try{xmlHttp=newActiveXObject("");}catch(e2){xmlHttp=false;}}@end@*/if(!xmlHttp&&typeofXMLHttpRequest!='undefined'){xmlHttp=newXMLHttpRequest();}現(xiàn)在先不管那些注釋掉的奇怪符號,如@cc_on,這是特殊的javascript編譯器命令,將在下一期針對XMLHttpRequest的文章中詳細討論。這段代碼的核心分為三步:建立一個變量xmlHttp來引用即將創(chuàng)建的XMLHttpRequest對象。嘗試在Microsoft瀏覽器中創(chuàng)建該對象:嘗試使用對象創(chuàng)建它。如果失敗,再嘗試對象。如果仍然沒有建立xmlHttp,則以非Microsoft的方式創(chuàng)建該對象。最后,xmlHttp應(yīng)該引用一個有效的XMLHttpRequest對象,無論運行什么樣的瀏覽器。關(guān)于安全性的一點說明安全性如何呢現(xiàn)在瀏覽器允許用戶提高他們的安全等級,關(guān)閉javascript技術(shù),禁用瀏覽器中的任何選項。在這種情況下,代碼無論如何都不會工作。此時必須適當?shù)靥幚韱栴},這需要單獨的一篇文章來討論,要放到以后了(這個系列夠長了吧不用擔心,讀完之前也許您就掌握了)?,F(xiàn)在要編寫一段健壯但不夠完美的代碼,對于掌握Ajax來說就很好了。以后我們還將討論更多的細節(jié)。Ajax世界中的請求/響應(yīng)現(xiàn)在我們介紹了Ajax,對XMLHttpRequest對象以及如何創(chuàng)建它也有了基本的了解。如果閱讀得很仔細,您可能已經(jīng)知道與服務(wù)器上的Web應(yīng)用程序打交道的是javascript技術(shù),而不是直接提交給那個應(yīng)用程序的HTML表單。還缺少什么呢到底如何使用XMLHttpRequest。因為這段代碼非常重要,您編寫的每個Ajax應(yīng)用程序都要以某種形式使用它,先看看Ajax的基本請求/響應(yīng)模型是什么樣吧。發(fā)出請求您已經(jīng)有了一個嶄新的XMLHttpRequest對象,現(xiàn)在讓它干點活兒吧。首先需要一個Web頁面能夠調(diào)用的javascript方法(比如當用戶輸入文本或者從菜單中選擇一項時)。接下來就是在所有Ajax應(yīng)用程序中基本都雷同的流程:從Web表單中獲取需要的數(shù)據(jù)。建立要連接的URL。打開到服務(wù)器的連接。設(shè)置服務(wù)器在完成后要運行的函數(shù)。發(fā)送請求。清單5中的示例Ajax方法就是按照這個順序組織的:清單5.發(fā)出Ajax請求functioncallServer(){alue;varstate=("state").value;處理服務(wù)器響應(yīng)functionupdatePage(){if==4){varresponse=;("zipCode").value=response;}}這些代碼同樣既不難也不復(fù)雜。它等待服務(wù)器調(diào)用,如果是就緒狀態(tài),則使用服務(wù)器返回的值(這里是用戶輸入的城市和州的ZIP編碼)設(shè)置另一個表單字段的值。于是包含ZIP編碼的zipCode字段突然出現(xiàn)了,而用戶沒有按任何按鈕!這就是前面所說的桌面應(yīng)用程序的感覺。快速響應(yīng)、動態(tài)感受等等,這些都只因為有了小小的一段Ajax代碼。細心的讀者可能注意到zipCode是一個普通的文本字段。一旦服務(wù)器返回ZIP編碼,updatePage()方法就用城市/州的ZIP編碼設(shè)置那個字段的值,用戶就可以改寫該值。這樣做有兩個原因:保持例子簡單,說明有時候可能希望用戶能夠修改服務(wù)器返回的數(shù)據(jù)。要記住這兩點,它們對于好的用戶界面設(shè)計來說很重要。連接Web表單還有什么呢實際上沒有多少了。一個javascript方法捕捉用戶輸入表單的信息并將其發(fā)送到服務(wù)器,另一個javascript方法監(jiān)聽和處理響應(yīng),并在響應(yīng)返回時設(shè)置字段的值。所有這些實際上都依賴于調(diào)用第一個javascript方法,它啟動了整個過程。最明顯的辦法是在HTML表單中增加一個按鈕,但這是2001年的辦法,您不這樣認為嗎還是像清單7這樣利用javascript技術(shù)吧。清單7.啟動一個Ajax過程<form><p>City:<inputtype="text"name="city"id="city"size="25"onChange="callServer();"/></p><p>State:<inputtype="text"name="state"id="state"size="25"onChange="callServer();"/></p><p>ZipCode:<inputtype="text"name="zipCode"id="city"size="5"/></p></form>如果感覺這像是一段相當普通的代碼,那就對了,正是如此!當用戶在city或state字段中輸入新的值時,callServer()方法就被觸發(fā),于是Ajax開始運行了。有點兒明白怎么回事了吧好,就是如此!結(jié)束語現(xiàn)在您可能已經(jīng)準備開始編寫第一個Ajax應(yīng)用程序了,至少也希望認真讀一下參考資料中的那些文章了吧但可以首先從這些應(yīng)用程序如何工作的基本概念開始,對XMLHttpRequest對象有基本的了解。在下一期文章中,您將掌握這個對象,學(xué)會如何處理javascript和服務(wù)器的通信、如何使用HTML表單以及如何獲得DOM句柄?,F(xiàn)在先花點兒時間考慮考慮Ajax應(yīng)用程序有多么強大。設(shè)想一下,當單擊按鈕、輸入一個字段、從組合框中選擇一個選項或者用鼠標在屏幕上拖動時,Web表單能夠立刻作出響應(yīng)會是什么情形。想一想異步究竟意味著什么,想一想javascript代碼運行而且不等待服務(wù)器對它的請求作出響應(yīng)。會遇到什么樣的問題會進入什么樣的領(lǐng)域考慮到這種新的方法,編程的時候應(yīng)如何改變表單的設(shè)計如果在這些問題上花一點兒時間,與簡單地剪切/粘貼某些代碼到您根本不理解的應(yīng)用程序中相比,收益會更多。在下一期文章中,我們將把這些概念付諸實踐,詳細介紹使應(yīng)用程序按照這種方式工作所需要的代碼。因此,現(xiàn)在先享受一下Ajax所帶來的可能性吧。參考資料學(xué)習(xí)您可以參閱本文在developerWorks全球站點上的英文原文。AdaptivePath是一家領(lǐng)先的用戶界面設(shè)計公司,仔細閱讀他們的網(wǎng)站可以更多地了解Ajax。如果關(guān)心Ajax一詞的來歷,請看一看JesseJamesGarrett和他的Ajax文章(比如這一篇)。可以先了解下一期文章的主題XMLHttpRequest對象,請閱讀關(guān)于XMLHttpRequest對象的這篇文章。如果使用InternetExplorer,可以訪問MicrosoftDeveloperNetwork的XMLDeveloperCenter。面向Java開發(fā)人員的Ajax:構(gòu)建動態(tài)的Java應(yīng)用程序(developerWorks,2005年9月)介紹了這種革新方法,它解決了頁面重新加載難題,可以創(chuàng)建動態(tài)的Web應(yīng)用程序體驗。面向Java開發(fā)人員的Ajax:Ajax的Java對象序列化(developerWorks,2005年10月)介紹了在Ajax應(yīng)用程序中對數(shù)據(jù)進行序列化的五種方法。UsingAjaxwithPHPandSajax(developerWorks,2005年10月),這篇教程針對那些對開發(fā)豐富Web應(yīng)用程序感興趣的人,介紹了使用Ajax和PHP動態(tài)更新內(nèi)容。CallSOAPWebserviceswithAJAX,Part1:BuildtheWebservicesclient(developerWorks,2005年10月)介紹了如何使用Ajax設(shè)計模式實現(xiàn)基于Web瀏覽器的SOAPWeb服務(wù)客戶機。XML問題:超越DOM(developerWorks,2005年5月)詳細闡述了如何使用文檔對象模型來構(gòu)建動態(tài)Web應(yīng)用程序。BuildappswithAsynchronousjavascriptwithXML,orAJAX(developerWorks,2005年11月)演示了如何使用Ajax構(gòu)造支持實時檢驗的Web應(yīng)用程序。面向Java開發(fā)人員的Ajax:結(jié)合DirectWebRemoting使用Ajax(developerWorks,2005年11月)演示了如何實現(xiàn)Ajax的繁瑣細節(jié)的自動化處理。OSAFoundation有一個wiki調(diào)查了AJAX/javascript庫。XULPlanet的對象參考部分詳細介紹了XMLHttpRequest對象(更不用說其他各種XML對象了,如DOM、CSS、HTML、WebService以及Windows和Navigation對象)。關(guān)于AJax的基本原理,請閱讀策略白皮書。請看看上展示的一些很棒的Ajax應(yīng)用程序。Google的GMail是另一個利用Ajax的革命性Web應(yīng)用程序的例子。HeadRushAjax(O'ReillyMedia,Inc.,2006年2月)包含了本文以及本系列文章所述的內(nèi)容(還有更多),并采用了創(chuàng)新的獲獎格式HeadFirst。javascript:TheDefinitiveGuide,第4版(O'ReillyMedia,Inc.,2001年11月)是關(guān)于javascript語言和使用動態(tài)網(wǎng)頁的好資料。developerWorksWeb體系結(jié)構(gòu)專區(qū)專門發(fā)表關(guān)于各種基于Web的解決方案的文章。討論加入本文的論壇。(您也可以通過點擊文章頂部或者底部的論壇鏈接參加討論。)Professional是關(guān)于Ajax各個方面的很好的blog。通過參與developerWorksblog加入developerWorks社區(qū)。關(guān)于作者BrettMcLaughlin從Logo時代就開始使用計算機。(還記得那個小三角嗎)近年來,他已經(jīng)成為Java和XML社區(qū)最著名的作者和程序員之一。他曾經(jīng)在NextelCommunications實現(xiàn)過復(fù)雜的企業(yè)系統(tǒng),在LutrisTechnologies編寫過應(yīng)用服務(wù)器,最近在O'ReillyMedia,Inc.繼續(xù)撰寫和編輯這方面的圖書。Brett即將出版的新書HeadRushAjax,和暢銷書作者Eric與BethFreeman一起為Ajax帶來了獲獎的革命性HeadFirst方法。最近的著作JavaTiger:ADeveloper'sNotebook是關(guān)于Java技術(shù)最新版本的第一本書,經(jīng)典的JavaandXML仍然是在Java語言中使用XML技術(shù)的權(quán)威著作。在Web請求中使用XMLHttpRequest級別:中級BrettMcLaughlin,作家,編輯,O'ReillyMediaInc.2006年2月16日多數(shù)Web應(yīng)用程序都使用請求/響應(yīng)模型從服務(wù)器上獲得完整的HTML頁面。常常是點擊一個按鈕,等待服務(wù)器響應(yīng),再點擊另一個按鈕,然后再等待,這樣一個反復(fù)的過程。有了Ajax和XMLHttpRequest對象,就可以使用不必讓用戶等待服務(wù)器響應(yīng)的請求/響應(yīng)模型了。本文中,BrettMcLaughlin介紹了如何創(chuàng)建能夠適應(yīng)不同瀏覽器的XMLHttpRequest實例,建立和發(fā)送請求,并響應(yīng)服務(wù)器。本系列的上一期文章(請參閱參考資料中的鏈接),我們介紹了Ajax應(yīng)用程序,考察了推動Ajax應(yīng)用程序的基本概念。其中的核心是很多您可能已經(jīng)了解的技術(shù):javascript、HTML和XHTML、一點動態(tài)HTML以及DOM(文檔對象模型)。本文將放大其中的一點,把目光放到具體的Ajax細節(jié)上。本文中,您將開始接觸最基本和基礎(chǔ)性的有關(guān)Ajax的全部對象和編程方法:XMLHttpRequest對象。該對象實際上僅僅是一個跨越所有Ajax應(yīng)用程序的公共線程,您可能已經(jīng)預(yù)料到,只有徹底理解該對象才能充分發(fā)揮編程的潛力。事實上,有時您會發(fā)現(xiàn),要正確地使用XMLHttpRequest,顯然不能使用XMLHttpRequest。這到底是怎么回事呢Web一瞥在深入研究代碼之前首先看看最近的觀點——一定要十分清楚Web這個概念。聽到Web這個詞的時候,應(yīng)該首先問一問“Web是什么”雖然很少聽人提到Web,實際上它指的就是具有完全不同的請求和響應(yīng)模型的傳統(tǒng)Web。比如,到網(wǎng)站上點擊一個按鈕或者輸入搜索項。就會對服務(wù)器發(fā)送一個請求,然后響應(yīng)再返回到瀏覽器。該請求不僅僅是圖書和書目列表,而是另一個完整的HTML頁面。因此當Web瀏覽器用新的HTML頁面重繪時,可能會看到閃爍或抖動。事實上,通過看到的每個新頁面可以清晰地看到請求和響應(yīng)。Web(在很大程度上)消除了這種看得見的往復(fù)交互。比如訪問GoogleMaps或Flickr這樣的站點(到這些支持Web和Ajax站點的鏈接請參閱參考資料)。比如在GoogleMaps上,您可以拖動地圖,放大和縮小,只有很少的重繪操作。當然這里仍然有請求和響應(yīng),只不過都藏到了幕后。作為用戶,體驗更加舒適,感覺很像桌面應(yīng)用程序。這種新的感受和范型就是當有人提到Web時您所體會到的。需要關(guān)心的是如何使這些新的交互成為可能。顯然,仍然需要發(fā)出請求和接收響應(yīng),但正是針對每次請求/響應(yīng)交互的HTML重繪造成了緩慢、笨拙的Web交互的感受。因此很清楚,我們需要一種方法使發(fā)送的請求和接收的響應(yīng)只包含需要的數(shù)據(jù)而不是整個HTML頁面。惟一需要獲得整個新HTML頁面的時候就是希望用戶看到新頁面的時候。但多數(shù)交互都是在已有頁面上增加細節(jié)、修改主體文本或者覆蓋原有數(shù)據(jù)。這些情況下,Ajax和Web方法允許在不更新整個HTML頁面的情況下發(fā)送和接收數(shù)據(jù)。對于那些經(jīng)常上網(wǎng)的人,這種能力可以讓您的應(yīng)用程序感覺更快、響應(yīng)更及時,讓他們不時地光顧您的網(wǎng)站。XMLHttpRequest簡介要真正實現(xiàn)這種絢麗的奇跡,必須非常熟悉一個javascript對象,即XMLHttpRequest。這個小小的對象實際上已經(jīng)在幾種瀏覽器中存在一段時間了,它是本專欄今后幾個月中要介紹的Web、Ajax和大部分其他內(nèi)容的核心。為了讓您快速地大體了解它,下面給出將要用于該對象的很少的幾個方法和屬性。open():建立到服務(wù)器的新請求。send():向服務(wù)器發(fā)送請求。abort():退出當前請求。readyState:提供當前HTML的就緒狀態(tài)。responseText:服務(wù)器返回的請求響應(yīng)文本。如果不了解這些(或者其中的任何一個),您也不用擔心,后面幾篇文章中我們將介紹每個方法和屬性?,F(xiàn)在應(yīng)該了解的是,明確用XMLHttpRequest做什么。要注意這些方法和屬性都與發(fā)送請求及處理響應(yīng)有關(guān)。事實上,如果看到XMLHttpRequest的所有方法和屬性,就會發(fā)現(xiàn)它們都與非常簡單的請求/響應(yīng)模型有關(guān)。顯然,我們不會遇到特別新的GUI對象或者創(chuàng)建用戶交互的某種超極神秘的方法,我們將使用非常簡單的請求和非常簡單的響應(yīng)。聽起來似乎沒有多少吸引力,但是用好該對象可以徹底改變您的應(yīng)用程序。簡單的new首先需要創(chuàng)建一個新變量并賦給它一個XMLHttpRequest對象實例。這在javascript中很簡單,只要對該對象名使用new關(guān)鍵字即可,如清單1所示。清單1.創(chuàng)建新的XMLHttpRequest對象<scriptlanguage="javascript"type="text/javascript">varrequest=newXMLHttpRequest();</script>不難吧記住,javascript不要求指定變量類型,因此不需要像清單2那樣做(在Java語言中可能需要這樣)。清單2.創(chuàng)建XMLHttpRequest的Java偽代碼XMLHttpRequestrequest=newXMLHttpRequest();因此在javascript中用var創(chuàng)建一個變量,給它一個名字(如“request”),然后賦給它一個新的XMLHttpRequest實例。此后就可以在函數(shù)中使用該對象了。錯誤處理在實際上各種事情都可能出錯,而上面的代碼沒有提供任何錯誤處理。較好的辦法是創(chuàng)建該對象,并在出現(xiàn)問題時優(yōu)雅地退出。比如,任何較早的瀏覽器(不論您是否相信,仍然有人在使用老版本的NetscapeNavigator)都不支持XMLHttpRequest,您需要讓這些用戶知道有些地方出了問題。清單3說明如何創(chuàng)建該對象,以便在出現(xiàn)問題的時候發(fā)出javascript警告。清單3.創(chuàng)建具有錯誤處理能力的XMLHttpRequest<scriptlanguage="javascript"type="text/javascript">varrequest=false;try{request=newXMLHttpRequest();}catch(failed){request=false;}if(!request)alert("ErrorinitializingXMLHttpRequest!");</script>一定要理解這些步驟:創(chuàng)建一個新變量request并賦值false。后面將使用false作為判定條件,它表示還沒有創(chuàng)建XMLHttpRequest對象。增加try/catch塊:嘗試創(chuàng)建XMLHttpRequest對象。如果失敗(catch(failed))則保證request的值仍然為false。檢查request是否仍為false(如果一切正常就不會是false)。如果出現(xiàn)問題(request是false)則使用javascript警告通知用戶出現(xiàn)了問題。代碼非常簡單,對大多數(shù)javascript和Web開發(fā)人員來說,真正理解它要比讀寫代碼花更長的時間。現(xiàn)在已經(jīng)得到了一段帶有錯誤檢查的XMLHttpRequest對象創(chuàng)建代碼,還可以告訴您哪兒出了問題。應(yīng)付Microsoft看起來似乎一切良好,至少在用InternetExplorer試驗這些代碼之前是這樣的。如果這樣試驗的話,就會看到圖1所示的糟糕情形。圖1.InternetExplorer報告錯誤Microsoft參與了嗎關(guān)于Ajax和Microsoft對該領(lǐng)域不斷增長的興趣和參與已經(jīng)有很多文章進行了介紹。事實上,據(jù)說Microsoft最新版本的InternetExplorer——version,將在2006年下半年推出——將開始直接支持XMLHttpRequest,讓您使用new關(guān)鍵字代替所有的創(chuàng)建代碼。但不要太激動,仍然需要支持舊的瀏覽器,因此跨瀏覽器代碼不會很快消失。顯然有什么地方不對勁,而InternetExplorer很難說是一種過時的瀏覽器,因為全世界有70%在使用InternetExplorer。換句話說,如果不支持Microsoft和InternetExplorer就不會受到Web世界的歡迎!因此我們需要采用不同的方法處理Microsoft瀏覽器。經(jīng)驗證發(fā)現(xiàn)Microsoft支持Ajax,但是其XMLHttpRequest版本有不同的稱呼。事實上,它將其稱為幾種不同的東西。如果使用較新版本的InternetExplorer,則需要使用對象,而較老版本的InternetExplorer則使用。我們需要支持這兩種對象類型(同時還要支持非Microsoft瀏覽器)。請看看清單4,它在前述代碼的基礎(chǔ)上增加了對Microsoft的支持。清單4.增加對Microsoft瀏覽器的支持<scriptlanguage="javascript"type="text/javascript">varrequest=false;try{request=newXMLHttpRequest();}catch(trymicrosoft){try{request=newActiveXObject("");}catch(othermicrosoft){try{request=newActiveXObject("");}catch(failed){request=false;}}}if(!request)alert("ErrorinitializingXMLHttpRequest!");</script>很容易被這些花括號迷住了眼睛,因此下面分別介紹每一步:創(chuàng)建一個新變量request并賦值false。使用false作為判斷條件,它表示還沒有創(chuàng)建XMLHttpRequest對象。增加try/catch塊:嘗試創(chuàng)建XMLHttpRequest對象。如果失敗(catch(trymicrosoft)):嘗試使用較新版本的Microsoft瀏覽器創(chuàng)建Microsoft兼容的對象()。如果失敗(catch(othermicrosoft))嘗試使用較老版本的Microsoft瀏覽器創(chuàng)建Microsoft兼容的對象()。如果失敗(catch(failed))則保證request的值仍然為false。檢查request是否仍然為false(如果一切順利就不會是false)。如果出現(xiàn)問題(request是false)則使用javascript警告通知用戶出現(xiàn)了問題。這樣修改代碼之后再使用InternetExplorer試驗,就應(yīng)該看到已經(jīng)創(chuàng)建的表單(沒有錯誤消息)。我實驗的結(jié)果如圖2所示。圖2.InternetExplorer正常工作靜態(tài)與動態(tài)再看一看清單1、3和4,注意,所有這些代碼都直接嵌套在script標記中。像這種不放到方法或函數(shù)體中的javascript代碼稱為靜態(tài)javascript。就是說代碼是在頁面顯示給用戶之前的某個時候運行。(雖然根據(jù)規(guī)范不能完全精確地知道這些代碼何時運行對瀏覽器有什么影響,但是可以保證這些代碼在用戶能夠與頁面交互之前運行。)這也是多數(shù)Ajax程序員創(chuàng)建XMLHttpRequest對象的一般方式。就是說,也可以像清單5那樣將這些代碼放在一個方法中。清單5.將XMLHttpRequest創(chuàng)建代碼移動到方法中<scriptlanguage="javascript"type="text/javascript">varrequest;functioncreateRequest(){try{request=newXMLHttpRequest();}catch(trymicrosoft){try{request=newActiveXObject("");}catch(othermicrosoft){try{request=newActiveXObject("");}catch(failed){request=false;}}}if(!request)alert("ErrorinitializingXMLHttpRequest!");}</script>如果按照這種方式編寫代碼,那么在處理Ajax之前需要調(diào)用該方法。因此還需要清單6這樣的代碼。清單6.使用XMLHttpRequest的創(chuàng)建方法<scriptlanguage="javascript"type="text/javascript">varrequest;functioncreateRequest(){try{request=newXMLHttpRequest();}catch(trymicrosoft){try{request=newActiveXObject("");}catch(othermicrosoft){try{request=newActiveXObject("");}catch(failed){request=false;}}}if(!request)alert("ErrorinitializingXMLHttpRequest!");}functiongetCustomerInfo(){createRequest();建立請求URL<scriptlanguage="javascript"type="text/javascript">varrequest=false;try{request=newXMLHttpRequest();}catch(trymicrosoft){try{request=newActiveXObject("");}catch(othermicrosoft){try{request=newActiveXObject("");}catch(failed){request=false;}}}if(!request)alert("ErrorinitializingXMLHttpRequest!");functiongetCustomerInfo(){varphone=("phone").value;varurl="/cgi-local/phone="+escape(phone);}</script>這里沒有難懂的地方。首先,代碼創(chuàng)建了一個新變量phone,并把ID為“phone”的表單字段的值賦給它。清單8展示了這個表單的XHTML,其中可以看到phone字段及其id屬性。清單8.BreakNeckPizza表單<body><p><imgsrc="4c"alt="BreakNeckPizza"/></p><formaction="POST"><p>Enteryourphonenumber:<inputtype="text"size="14"name="phone"id="phone"onChange="getCustomerInfo();"/></p><p>Yourorderwillbedeliveredto:</p><divid="address"></div><p>Typeyourorderinhere:</p><p><textareaname="order"rows="6"cols="50"id="order"></textarea></p><p><inputtype="submit"value="OrderPizza"id="submit"/></p></form></body>還要注意,當用戶輸入電話號碼或者改變電話號碼時,將觸發(fā)清單8所示的getCustomerInfo()方法。該方法取得電話號碼并構(gòu)造存儲在url變量中的URL字符串。記住,由于Ajax代碼是沙箱型的,因而只能連接到同一個域,實際上URL中不需要域名。該例中的腳本名為/cgi-local/。最后,電話號碼作為GET參數(shù)附加到該腳本中:"phone="+escape(phone)。如果以前沒用見過escape()方法,它用于轉(zhuǎn)義不能用明文正確發(fā)送的任何字符。比如,電話號碼中的空格將被轉(zhuǎn)換成字符%20,從而能夠在URL中傳遞這些字符??梢愿鶕?jù)需要添加任意多個參數(shù)。比如,如果需要增加另一個參數(shù),只需要將其附加到URL中并用“與”(&)字符分開[第一個參數(shù)用問號()和腳本名分開]。打開請求open()是打開嗎Internet開發(fā)人員對open()方法到底做什么沒有達成一致。但它實際上并不是打開一個請求。如果監(jiān)控XHTML/Ajax頁面及其連接腳本之間的網(wǎng)絡(luò)和數(shù)據(jù)傳遞,當調(diào)用open()方法時將看不到任何通信。不清楚為何選用了這個名字,但顯然不是一個好的選擇。有了要連接的URL后就可以配置請求了。可以用XMLHttpRequest對象的open()方法來完成。該方法有五個參數(shù):request-type:發(fā)送請求的類型。典型的值是GET或POST,但也可以發(fā)送HEAD請求。url:要連接的URL。asynch:如果希望使用異步連接則為true,否則為false。該參數(shù)是可選的,默認為true。username:如果需要身份驗證,則可以在此指定用戶名。該可選參數(shù)沒有默認值。password:如果需要身份驗證,則可以在此指定口令。該可選參數(shù)沒有默認值。通常使用其中的前三個參數(shù)。事實上,即使需要異步連接,也應(yīng)該指定第三個參數(shù)為“true”。這是默認值,但堅持明確指定請求是異步的還是同步的更容易理解。將這些結(jié)合起來,通常會得到清單9所示的一行代碼。清單9.打開請求functiongetCustomerInfo(){varphone=("phone").value;varurl="/cgi-local/phone="+escape(phone);("GET",url,true);}一旦設(shè)置好了URL,其他就簡單了。多數(shù)請求使用GET就夠了(后面的文章中將看到需要使用POST的情況),再加上URL,這就是使用open()方法需要的全部內(nèi)容了。挑戰(zhàn)異步性本系列的后面一篇文章中,我將用很多時間編寫和使用異步代碼,但是您應(yīng)該明白為什么open()的最后一個參數(shù)這么重要。在一般的請求/響應(yīng)模型中,比如Web,客戶機(瀏覽器或者本地機器上運行的代碼)向服務(wù)器發(fā)出請求。該請求是同步的,換句話說,客戶機等待服務(wù)器的響應(yīng)。當客戶機等待的時候,至少會用某種形式通知您在等待:沙漏(特別是Windows上)。旋轉(zhuǎn)的皮球(通常在Mac機器上)。應(yīng)用程序基本上凍結(jié)了,然后過一段時間光標變化了。這正是Web應(yīng)用程序讓人感到笨拙或緩慢的原因——缺乏真正的交互性。按下按鈕時,應(yīng)用程序?qū)嶋H上變得不能使用,直到剛剛觸發(fā)的請求得到響應(yīng)。如果請求需要大量服務(wù)器處理,那么等待的時間可能很長(至少在這個多處理器、DSL沒有等待的世界中是如此)。而異步請求不等待服務(wù)器響應(yīng)。發(fā)送請求后應(yīng)用程序繼續(xù)運行。用戶仍然可以在Web表單中輸入數(shù)據(jù),甚至離開表單。沒有旋轉(zhuǎn)的皮球或者沙漏,應(yīng)用程序也沒有明顯的凍結(jié)。服務(wù)器悄悄地響應(yīng)請求,完成后告訴原來的請求者工作已經(jīng)結(jié)束(具體的辦法很快就會看到)。結(jié)果是,應(yīng)用程序感覺不那么遲鈍或者緩慢,而是響應(yīng)迅速、交互性強,感覺快多了。這僅僅是Web的一部分,但它是很重要的一部分。所有老套的GUI組件和Web設(shè)計范型都不能克服緩慢、同步的請求/響應(yīng)模型。發(fā)送請求一旦用open()配置好之后,就可以發(fā)送請求了。幸運的是,發(fā)送請求的方法的名稱要比open()適當,它就是send()。send()只有一個參數(shù),就是要發(fā)送的內(nèi)容。但是在考慮這個方法之前,回想一下前面已經(jīng)通過URL本身發(fā)送過數(shù)據(jù)了:varurl="/cgi-local/phone="+escape(phone);雖然可以使用send()發(fā)送數(shù)據(jù),但也能通過URL本身發(fā)送數(shù)據(jù)。事實上,GET請求(在典型的Ajax應(yīng)用中大約占80%)中,用URL發(fā)送數(shù)據(jù)要容易得多。如果需要發(fā)送安全信息或XML,可能要考慮使用send()發(fā)送內(nèi)容(本系列的后續(xù)文章中將討論安全數(shù)據(jù)和XML消息)。如果不需要通過send()傳遞數(shù)據(jù),則只要傳遞null作為該方法的參數(shù)即可。因此您會發(fā)現(xiàn)在本文中的例子中只需要這樣發(fā)送請求(參見清單10)。清單10.發(fā)送請求functiongetCustomerInfo(){varphone=("phone").value;varurl="/cgi-local/phone="+escape(phone);("GET",url,true);(null);}指定回調(diào)方法現(xiàn)在我們所做的只有很少一點是新的、革命性的或異步的。必須承認,open()方法中“true”這個小小的關(guān)鍵字建立了異步請求。但是除此之外,這些代碼與用Javaservlet及JSP、PHP或Perl編程沒有什么兩樣。那么Ajax和Web最大的秘密是什么呢秘密就在于XMLHttpRequest的一個簡單屬性onreadystatechange。首先一定要理解這些代碼中的流程(如果需要請回顧清單10)。建立其請求然后發(fā)出請求。此外,因為是異步請求,所以javascript方法(例子中的getCustomerInfo())不會等待服務(wù)器。因此代碼將繼續(xù)執(zhí)行,就是說,將退出該方法而把控制返回給表單。用戶可以繼續(xù)輸入信息,應(yīng)用程序不會等待服務(wù)器。這就提出了一個有趣的問題:服務(wù)器完成了請求之后會發(fā)生什么答案是什么也不發(fā)生,至少對現(xiàn)在的代碼而言如此!顯然這樣不行,因此服務(wù)器在完成通過XMLHttpRequest發(fā)送給它的請求處理之后需要某種指示說明怎么做。在javascript中引用函數(shù)javascript是一種弱類型的語言,可以用變量引用任何東西。因此如果聲明了一個函數(shù)updatePage(),javascript也將該函數(shù)名看作是一個變量。換句話說,可用變量名updatePage在代碼中引用函數(shù)?,F(xiàn)在onreadystatechange屬性該登場了。該屬性允許指定一個回調(diào)函數(shù)?;卣{(diào)允許服務(wù)器(猜得到嗎)反向調(diào)用Web頁面中的代碼。它也給了服務(wù)器一定程度的控制權(quán),當服務(wù)器完成請求之后,會查看XMLHttpRequest對象,特別是onreadystatechange屬性。然后調(diào)用該屬性指定的任何方法。之所以稱為回調(diào)是因為服務(wù)器向網(wǎng)頁發(fā)起調(diào)用,無論網(wǎng)頁本身在做什么。比方說,可能在用戶坐在椅子上手沒有碰鍵盤的時候調(diào)用該方法,但是也可能在用戶輸入、移動鼠標、滾動屏幕或者點擊按鈕時調(diào)用該方法。它并不關(guān)心用戶在做什么。這就是稱之為異步的原因:用戶在一層上操作表單,而在另一層上服務(wù)器響應(yīng)請求并觸發(fā)onreadystatechange屬性指定的回調(diào)方法。因此需要像清單11一樣在代碼中指定該方法。清單11.設(shè)置回調(diào)方法functiongetCustomerInfo(){varphone=("phone").value;varurl="/cgi-local/phone="+escape(phone);("GET",url,true);=updatePage;(null);}需要特別注意的是該屬性在代碼中設(shè)置的位置——它是在調(diào)用send()之前設(shè)置的。發(fā)送請求之前必須設(shè)置該屬性,這樣服務(wù)器在回答完成請求之后才能查看該屬性?,F(xiàn)在剩下的就只有編寫updatePage()方法了,這是本文最后一節(jié)要討論的重點。處理服務(wù)器響應(yīng)發(fā)送請求,用戶高興地使用Web表單(同時服務(wù)器在處理請求),而現(xiàn)在服務(wù)器完成了請求處理。服務(wù)器查看onreadystatechange屬性確定要調(diào)用的方法。除此以外,可以將您的應(yīng)用程序看作其他應(yīng)用程序一樣,無論是否異步。換句話說,不一定要采取特殊的動作編寫響應(yīng)服務(wù)器的方法,只需要改變表單,讓用戶訪問另一個URL或者做響應(yīng)服務(wù)器需要的任何事情。這一節(jié)我們重點討論對服務(wù)器的響應(yīng)和一種典型的動作——即時改變用戶看到的表單中的一部分?;卣{(diào)和Ajax現(xiàn)在我們已經(jīng)看到如何告訴服務(wù)器完成后應(yīng)該做什么:將XMLHttpRequest對象的onreadystatechange屬性設(shè)置為要運行的函數(shù)名。這樣,當服務(wù)器處理完請求后就會自動調(diào)用該函數(shù)。也不需要擔心該函數(shù)的任何參數(shù)。我們從一個簡單的方法開始,如清單12所示。清單12.回調(diào)方法的代碼<scriptlanguage="javascript"type="text/javascript">varrequest=false;try{request=newXMLHttpRequest();}catch(trymicrosoft){try{request=newActiveXObject("");}catch(othermicrosoft){try{request=newActiveXObject("");}catch(failed){request=false;}}}if(!request)alert("ErrorinitializingXMLHttpRequest!");functiongetCustomerInfo(){varphone=("phone").value;varurl="/cgi-local/phone="+escape(phone);("GET",url,true);=updatePage;(null);}functionupdatePage(){alert("Serverisdone!");}</script>它僅僅發(fā)出一些簡單的警告,告訴您服務(wù)器什么時候完成了任務(wù)。在自己的網(wǎng)頁中試驗這些代碼,然后在瀏覽器中打開(如果希望查看該例中的XHTML,請參閱清單8)。輸入電話號碼然后離開該字段,將看到一個彈出的警告窗口(如圖3所示),但是點擊OK又出現(xiàn)了……圖3.彈出警告的Ajax代碼根據(jù)瀏覽器的不同,在表單停止彈出警告之前會看到兩次、三次甚至四次警告。這是怎么回事呢原來我們還沒有考慮HTTP就緒狀態(tài),這是請求/響應(yīng)循環(huán)中的一個重要部分。HTTP就緒狀態(tài)前面提到,服務(wù)器在完成請求之后會在XMLHttpRequest的onreadystatechange屬性中查找要調(diào)用的方法。這是真的,但還不完整。事實上,每當HTTP就緒狀態(tài)改變時它都會調(diào)用該方法。這意味著什么呢首先必須理解HTTP就緒狀態(tài)。HTTP就緒狀態(tài)表示請求的狀態(tài)或情形。它用于確定該請求是否已經(jīng)開始、是否得到了響應(yīng)或者請求/響應(yīng)模型是否已經(jīng)完成。它還可以幫助確定讀取服務(wù)器提供的響應(yīng)文本或數(shù)據(jù)是否安全。在Ajax應(yīng)用程序中需要了解五種就緒狀態(tài):0:請求沒有發(fā)出(在調(diào)用open()之前)。1:請求已經(jīng)建立但還沒有發(fā)出(調(diào)用send()之前)。2:請求已經(jīng)發(fā)出正在處理之中(這里通??梢詮捻憫?yīng)得到內(nèi)容頭部)。3:請求已經(jīng)處理,響應(yīng)中通常有部分數(shù)據(jù)可用,但是服務(wù)器還沒有完成響應(yīng)。4:響應(yīng)已完成,可以訪問服務(wù)器響應(yīng)并使用它。與大多數(shù)跨瀏覽器問題一樣,這些就緒狀態(tài)的使用也不盡一致。您也許期望任務(wù)就緒狀態(tài)從0到1、2、3再到4,但實際上很少是這種情況。一些瀏覽器從不報告0或1而直接從2開始,然后是3和4。其他瀏覽器則報告所有的狀態(tài)。還有一些則多次報告就緒狀態(tài)1。在上一節(jié)中看到,服務(wù)器多次調(diào)用updatePage(),每次調(diào)用都會彈出警告框——可能和預(yù)期的不同!對于Ajax編程,需要直接處理的惟一狀態(tài)就是就緒狀態(tài)4,它表示服務(wù)器響應(yīng)已經(jīng)完成,可以安全地使用響應(yīng)數(shù)據(jù)了?;诖?,回調(diào)方法中的第一行應(yīng)該如清單13所示。清單13.檢查就緒狀態(tài)functionupdatePage(){if==4)alert("Serverisdone!");}修改后就可以保證服務(wù)器的處理已經(jīng)完成。嘗試運行新版本的Ajax代碼,現(xiàn)在就會看到與預(yù)期的一樣,只顯示一次警告信息了。HTTP狀態(tài)碼雖然清單13中的代碼看起來似乎不錯,但是還有一個問題——如果服務(wù)器響應(yīng)請求并完成了處理但是報告了一個錯誤怎么辦要知道,服務(wù)器端代碼應(yīng)該明白它是由Ajax、JSP、普通HTML表單或其他類型的代碼調(diào)用的,但只能使用傳統(tǒng)的Web專用方法報告信息。而在Web世界中,HTTP代碼可以處理請求中可能發(fā)生的各種問題。比方說,您肯定遇到過輸入了錯誤的URL請求而得到404錯誤碼的情形,它表示該頁面不存在。這僅僅是HTTP請求能夠收到的眾多錯誤碼中的一種(完整的狀態(tài)碼列表請參閱參考資料中的鏈接)。表示所訪問數(shù)據(jù)受到保護或者禁止訪問的403和401也很常見。無論哪種情況,這些錯誤碼都是從完成的響應(yīng)得到的。換句話說,服務(wù)器履行了請求(即HTTP就緒狀態(tài)是4)但是沒有返回客戶機預(yù)期的數(shù)據(jù)。因此除了就緒狀態(tài)外,還需要檢查HTTP狀態(tài)。我們期望的狀態(tài)碼是200,它表示一切順利。如果就緒狀態(tài)是4而且狀態(tài)碼是200,就可以處理服務(wù)器的數(shù)據(jù)了,而且這些數(shù)據(jù)應(yīng)該就是要求的數(shù)據(jù)(而不是錯誤或者其他有問題的信息)。因此還要在回調(diào)方法中增加狀態(tài)檢查,如清單14所示。清單14.檢查HTTP狀態(tài)碼functionupdatePage(){if==4)if==200)alert("Serverisdone!");}為了增加更健壯的錯誤處理并盡量避免過于復(fù)雜,可以增加一兩個狀態(tài)碼檢查,請看一看清單15中修改后的updatePage()版本。清單15.增加一點錯誤檢查functionupdatePage(){if==4)if==200)alert("Serverisdone!");elseif==404)alert("RequestURLdoesnotexist");elsealert("Error:statuscodeis"+;}現(xiàn)在將getCustomerInfo()中的URL改為不存在的URL看看會發(fā)生什么。應(yīng)該會看到警告信息說明要求的URL不存在——好極了!很難處理所有的錯誤條件,但是這一小小的改變能夠涵蓋典型Web應(yīng)用程序中80%的問題。讀取響應(yīng)文本現(xiàn)在可以確保請求已經(jīng)處理完成(通過就緒狀態(tài)),服務(wù)器給出了正常的響應(yīng)(通過狀態(tài)碼),最后我們可以處理服務(wù)器返回的數(shù)據(jù)了。返回的數(shù)據(jù)保存在XMLHttpRequest對象的responseText屬性中。關(guān)于responseText中的文本內(nèi)容,比如格式和長度,有意保持含糊。這樣服務(wù)器就可以將文本設(shè)置成任何內(nèi)容。比方說,一種腳本可能返回逗號分隔的值,另一種則使用管道符(即|字符)分隔的值,還有一種則返回長文本字符串。何去何從由服務(wù)器決定。在本文使用的例子中,服務(wù)器返回客戶的上一個訂單和客戶地址,中間用管道符分開。然后使用訂單和地址設(shè)置表單中的元素值,清單16給出了更新顯示內(nèi)容的代碼。清單16.處理服務(wù)器響應(yīng)functionupdatePage(){if==4){if==200){[B]varresponse="|");("order").value=response[0];("address").innerHTML=response[1].replace(/\n/g,"");[/B]}elsealert("statusis"+;}}首先,得到responseText并使用javascriptsplit()方法從管道符分開。得到的數(shù)組放到response中。數(shù)組中的第一個值——上一個訂單——用response[0]訪問,被設(shè)置為ID為“order”的字段的值。第二個值response[1],即客戶地址,則需要更多一點處理。因為地址中的行用一般的行分隔符(“\n”字符)分隔,代碼中需要用XHTML風格的行分隔符<br/>來代替。替換過程使用replace()函數(shù)和正則表達式完成。最后,修改后的文本作為HTML表單div中的內(nèi)部HTML。結(jié)果就是表單突然用客戶信息更新了,如圖4所示。圖4.收到客戶數(shù)據(jù)后的BreakNeck表單結(jié)束本文之前,我還要介紹XMLHttpRequest的另一個重要屬性responseXML。如果服務(wù)器選擇使用XML響應(yīng)則該屬性包含(也許您已經(jīng)猜到)XML響應(yīng)。處理XML響應(yīng)和處理普通文本有很大不同,涉及到解析、文檔對象模型(DOM)和其他一些問題。后面的文章中將進一步介紹XML。但是因為responseXML通常和responseText一起討論,這里有必要提一提。對于很多簡單的Ajax應(yīng)用程序responseText就夠了,但是您很快就會看到通過Ajax應(yīng)用程序也能很好地處理XML。結(jié)束語您可能對XMLHttpRequest感到有點厭倦了,我很少看到一整篇文章討論一個對象,特別是這種簡單的對象。但是您將在使用Ajax編寫的每個頁面和應(yīng)用程序中反復(fù)使用該對象。坦白地說,關(guān)于XMLHttpRequest還真有一些可說的內(nèi)容。下一期文章中將介紹如何在請求中使用POST及GET,來設(shè)置請求中的內(nèi)容頭部和從服務(wù)器響應(yīng)讀取內(nèi)容頭部,理解如何在請求/響應(yīng)模型中編碼請求和處理XML。再往后我們將介紹常見Ajax工具箱。這些工具箱實際上隱藏了本文所述的很多細節(jié),使得Ajax編程更容易。您也許會想,既然有這么多工具箱為何還要對底層的細節(jié)編碼。答案是,如果不知道應(yīng)用程序在做什么,就很難發(fā)現(xiàn)應(yīng)用程序中的問題。因此不要忽略這些細節(jié)或者簡單地瀏覽一下,如果便捷華麗的工具箱出現(xiàn)了錯誤,您就不必撓頭或者發(fā)送郵件請求支持了。如果了解如何直接使用XMLHttpRequest,就會發(fā)現(xiàn)很容易調(diào)試和解決最奇怪的問題。只有讓其解決您的問題,工具箱才是好東西。因此請熟悉XMLHttpRequest吧。事實上,如果您有使用工具箱的Ajax代碼,可以嘗試使用XMLHttpRequest對象及其屬性和方法重新改寫。這是一種不錯的練習(xí),可以幫助您更好地理解其中的原理。下一期文章中將進一步討論該對象,探討它的一些更有趣的屬性(如responseXML),以及如何使用POST請求和以不同的格式發(fā)送數(shù)據(jù)。請開始編寫代碼吧,一個月后我們再繼續(xù)討論。參考資料學(xué)習(xí)您可以參閱本文在developerWorks全球站點上的英文原文。掌握Ajax,第1部分:Ajax簡介(developerWorks,2005年12月)幫助您了解Ajax,這是一種構(gòu)建網(wǎng)站的高生產(chǎn)率方法。(本文中的參考資料列表都值得訪問!)面向Java開發(fā)人員的Ajax:構(gòu)建動態(tài)的Java應(yīng)用程序(developerWorks,2005年9月)從Java的角度考察了Ajax服務(wù)器端。面向Java開發(fā)人員的Ajax:Ajax的Java對象序列化(developerWorks,2005年10月)從Java的角度分析了如何通過網(wǎng)絡(luò)發(fā)送對象以及與Ajax交互。使用AJAX調(diào)用SOAPWeb服務(wù),第1部分:構(gòu)建Web服務(wù)客戶機(developerWorks,2005年10月)是關(guān)于集成Ajax和現(xiàn)有基于SOAP的web服務(wù)的相當高級的文章。GoogleGMail是一個很好的例子,說明了基于Ajax的應(yīng)用程序如何改變Web的工作方式。GoogleMaps是另一種基于Google的Web應(yīng)用程序。Flickr是一個很好的例子,說明如何使用Ajax創(chuàng)建類似桌面的Web應(yīng)用程序。Ajax:ANewApproachtoWebApplications發(fā)明了Ajax一詞,所有Ajax開發(fā)人員都應(yīng)該讀一讀。WhyAjaxMattersNow告訴您為什么Ajax很重要。如果使用的是Microsoft瀏覽器InternetExplorer,請訪問MicrosoftDeveloperNetwork'sXMLDeveloperCenter。請通過在線文檔進一步了解MSXML,MicrosoftXML解析器??匆豢错憫?yīng)中包含的所有HTTP狀態(tài)碼列表。developerWorksWebArchitecture專區(qū)專門發(fā)表各種基于Web的解決方案的文章。獲得產(chǎn)品和技術(shù)ElisabethFreeman、EricFreeman和BrettMcLaughlin合著的HeadRu
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025版木制家具生產(chǎn)加工木工合作合同范本4篇
- 2025版委托檢測合同書-光纖網(wǎng)絡(luò)性能檢測技術(shù)3篇
- 二零二五版水產(chǎn)品電商平臺大數(shù)據(jù)分析服務(wù)合同2篇
- 2025年度母子公司新能源儲能技術(shù)研發(fā)合作合同3篇
- 《吳組緗天下太平》課件
- 單板加工自動化與智能化技術(shù)考核試卷
- 2025版互聯(lián)網(wǎng)醫(yī)療投資項目融資借款合同3篇
- 《物價上漲時政》課件
- 2025年度木工工具租賃與施工服務(wù)承包合同4篇
- 2025年兒童玩具連鎖店加盟合同
- 農(nóng)民工工資表格
- 【寒假預(yù)習(xí)】專題04 閱讀理解 20篇 集訓(xùn)-2025年人教版(PEP)六年級英語下冊寒假提前學(xué)(含答案)
- 2024年智能監(jiān)獄安防監(jiān)控工程合同3篇
- 2024年度窯爐施工協(xié)議詳例細則版B版
- 幼兒園籃球課培訓(xùn)
- 【企業(yè)盈利能力探析的國內(nèi)外文獻綜述2400字】
- 統(tǒng)編版(2024新版)七年級《道德與法治》上冊第一單元《少年有夢》單元測試卷(含答案)
- 100道20以內(nèi)的口算題共20份
- 高三完形填空專項訓(xùn)練單選(部分答案)
- 護理查房高鉀血癥
- 項目監(jiān)理策劃方案匯報
評論
0/150
提交評論