中文字幕二区_国产精品免费在线观看_黄色网站观看_人人草人人澡_日本真实娇小xxxx

您的位置: 首頁 > 技術(shù)文檔 > 網(wǎng)絡(luò)編程 > 掌握 Ajax
FSO操作文件系統(tǒng) 回到列表 ObjectDataSourc控件
 掌握 Ajax

作者:Brett McLaughlin 時間: 2006-04-19 文檔類型:原創(chuàng) 來自:IBM developerWorks

第 1 頁 Ajax 簡介
第 2 頁 使用 JavaScript 和 Ajax 發(fā)出異步請求
第 3 頁 Ajax 中的高級請求和響應(yīng)
第 4 頁 利用 DOM 進(jìn)行 Web 響應(yīng)
第 5 頁 參考資料

對于很多 Web 開發(fā)人員來說,只需要生成簡單的請求并接收簡單的響應(yīng)即可;但是對于希望掌握 Ajax 的開發(fā)人員來說,必須要全面理解 HTTP 狀態(tài)代碼、就緒狀態(tài)和 XMLHttpRequest 對象。在本文中,Brett McLaughlin 將向您介紹各種狀態(tài)代碼,并展示瀏覽器如何對其進(jìn)行處理,本文還給出了在 Ajax 中使用的比較少見的 HTTP 請求。

在本系列的 上篇文章 中,我們將詳細(xì)介紹 XMLHttpRequest 對象,它是 Ajax 應(yīng)用程序的中心,負(fù)責(zé)處理服務(wù)器端應(yīng)用程序和腳本的請求,并處理從服務(wù)器端組件返回的數(shù)據(jù)。由于所有的 Ajax 應(yīng)用程序都要使用 XMLHttpRequest 對象,因此您可能會希望熟悉這個對象,從而能夠讓 Ajax 執(zhí)行得更好。

在本文中,我將在上一篇文章的基礎(chǔ)上重點(diǎn)介紹這個請求對象的 3 個關(guān)鍵部分的內(nèi)容:

·HTTP 就緒狀態(tài)
·HTTP 狀態(tài)代碼
·可以生成的請求類型

這三部分內(nèi)容都是在構(gòu)造一個請求時所要考慮的因素;但是介紹這些主題的內(nèi)容太少了。然而,如果您不僅僅是想了解 Ajax 編程的常識,而是希望了解更多內(nèi)容,就需要熟悉就緒狀態(tài)、狀態(tài)代碼和請求本身的內(nèi)容。當(dāng)應(yīng)用程序出現(xiàn)問題時 —— 這種問題總是存在 —— 那么如果能夠正確理解就緒狀態(tài)、如何生成一個 HEAD 請求或者 400 的狀態(tài)代碼的確切含義,就可以在 5 分鐘內(nèi)調(diào)試出問題,而不是在各種挫折和困惑中度過 5 個小時。

下面讓我們首先來看一下 HTTP 就緒狀態(tài)。

深入了解 HTTP 就緒狀態(tài)

您應(yīng)該還記得在上一篇文章中 XMLHttpRequest 對象有一個名為 readyState 的屬性。這個屬性確保服務(wù)器已經(jīng)完成了一個請求,通常會使用一個回調(diào)函數(shù)從服務(wù)器中讀出數(shù)據(jù)來更新 Web 表單或頁面的內(nèi)容。清單 1 給出了一個簡單的例子(這也是本系列的上一篇文章中的一個例子 —— 請參見 參考資料)。

 

XMLHttpRequest 或 XMLHttp:換名玫瑰

Microsoft™ 和 Internet Explorer 使用了一個名為 XMLHttp 的對象,而不是 XMLHttpRequest 對象,而 Mozilla、Opera、Safari 和 大部分非 Microsoft 瀏覽器都使用的是后者。為了簡單性起見,我將這兩個對象都簡單地稱為 XMLHttpRequest。這既符合我們在 Web 上看到的情況,又符合 Microsoft 在 Internet Explorer 7.0 中使用 XMLHttpRequest 作為請求對象的意圖。(有關(guān)這個問題的更多內(nèi)容,請參見 第 2 部分。)

清單 1. 在回調(diào)函數(shù)中處理服務(wù)器的響應(yīng)

 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, "<br />");
     } else
       alert("status is " + request.status);
   }
 }

這顯然是就緒狀態(tài)最常見(也是最簡單)的用法。正如您從數(shù)字 "4" 中可以看出的一樣,還有其他幾個就緒狀態(tài)(您在上一篇文章中也看到過這個清單 —— 請參見 參考資料):

·0:請求未初始化(還沒有調(diào)用 open())。
·1:請求已經(jīng)建立,但是還沒有發(fā)送(還沒有調(diào)用 send())。
·2:請求已發(fā)送,正在處理中(通常現(xiàn)在可以從響應(yīng)中獲取內(nèi)容頭)。
·3:請求在處理中;通常響應(yīng)中已有部分?jǐn)?shù)據(jù)可用了,但是服務(wù)器還沒有完成響應(yīng)的生成。
·4:響應(yīng)已完成;您可以獲取并使用服務(wù)器的響應(yīng)了。

如果您希望不僅僅是了解 Ajax 編程的基本知識,那么就不但需要知道這些狀態(tài),了解這些狀態(tài)是何時出現(xiàn)的,以及如何來使用這些狀態(tài)。首先,您需要學(xué)習(xí)在每種就緒狀態(tài)下可能碰到的是哪種請求狀態(tài)。不幸的是,這一點(diǎn)并不直觀,而且會涉及幾種特殊的情況。

隱秘就緒狀態(tài)

第一種就緒狀態(tài)的特點(diǎn)是 readyState 屬性為 0(readyState == 0),表示未初始化狀態(tài)。一旦對請求對象調(diào)用 open() 之后,這個屬性就被設(shè)置為 1。由于您通常都是在一對請求進(jìn)行初始化之后就立即調(diào)用 open(),因此很少會看到 readyState == 0 的狀態(tài)。另外,未初始化的就緒狀態(tài)在實(shí)際的應(yīng)用程序中是沒有真正的用處的。

不過為了滿足我們的興趣,請參見 清單 2 的內(nèi)容,其中顯示了如何在 readyState 被設(shè)置為 0 時來獲取這種就緒狀態(tài)。

清單 2. 獲取 0 就緒狀態(tài)

   function getSalesData() {
     // Create a request object
     createRequest();  
     alert("Ready state is: " + request.readyState);

     // Setup (initialize) the request
     var url = "/boards/servlet/UpdateBoardSales";
     request.open("GET", url, true);
     request.onreadystatechange = updatePage;
     request.send(null);
   }

在這個簡單的例子中,getSalesData() 是 Web 頁面調(diào)用來啟動請求(例如點(diǎn)擊一個按鈕時)所使用的函數(shù)。注意您必須在調(diào)用 open()之前 來查看就緒狀態(tài)。圖 1 給出了運(yùn)行這個應(yīng)用程序的結(jié)果。

圖 1. 就緒狀態(tài) 0

顯然,這并不能為您帶來多少好處;需要確保 尚未 調(diào)用 open() 函數(shù)的情況很少。在大部分 Ajax 編程的真實(shí)情況中,這種就緒狀態(tài)的唯一用法就是使用相同的 XMLHttpRequest 對象在多個函數(shù)之間生成多個請求。在這種(不常見的)情況中,您可能會在生成新請求之前希望確保請求對象是處于未初始化狀態(tài)(readyState == 0)。這實(shí)際上是要確保另外一個函數(shù)沒有同時使用這個對象。

查看正在處理的請求的就緒狀態(tài)

除了 0 就緒狀態(tài)之外,請求對象還需要依次經(jīng)歷典型的請求和響應(yīng)的其他幾種就緒狀態(tài),最后才以就緒狀態(tài) 4 的形式結(jié)束。這就是為什么您在大部分回調(diào)函數(shù)中都可以看到 if (request.readyState == 4) 這行代碼;它確保服務(wù)器已經(jīng)完成對請求的處理,現(xiàn)在可以安全地更新 Web 頁面或根據(jù)從服務(wù)器返回來的數(shù)據(jù)來進(jìn)行操作了。

要查看這種狀態(tài)發(fā)生的過程非常簡單。如果就緒狀態(tài)為 4,我們不僅要運(yùn)行回調(diào)函數(shù)中的代碼,而且還要在每次調(diào)用回調(diào)函數(shù)時都輸出就緒狀態(tài)。 清單 3 給出了一個實(shí)現(xiàn)這種功能的例子。

當(dāng) 0 等于 4 時

在多個 JavaScript 函數(shù)都使用相同的請求對象時,您需要檢查就緒狀態(tài) 0 來確保這個請求對象沒有正在使用,這種機(jī)制會產(chǎn)生問題。由于 readyState == 4 表示一個已完成的請求,因此您經(jīng)常會發(fā)現(xiàn)那些目前沒在使用的處于就緒狀態(tài)的請求對象仍然被設(shè)置成了 4 —— 這是因?yàn)閺姆⻊?wù)器返回來的數(shù)據(jù)已經(jīng)使用過了,但是從它們被設(shè)置為就緒狀態(tài)之后就沒有進(jìn)行任何變化。有一個函數(shù) abort() 會重新設(shè)置請求對象,但是這個函數(shù)卻不是真正為了這個目的而使用的。如果您 必須 使用多個函數(shù),最好是為每個函數(shù)都創(chuàng)建并使用一個函數(shù),而不是在多個函數(shù)之間共享相同的對象。

清單 3. 查看就緒狀態(tài)

   function updatePage() {
     // Output the current ready state
     alert("updatePage() called with ready state of " + request.readyState);
   }

如果您不確定如何運(yùn)行這個函數(shù),就需要創(chuàng)建一個函數(shù),然后在 Web 頁面中調(diào)用這個函數(shù),并讓它向服務(wù)器端的組件發(fā)送一個請求(例如 清單 2 給出的函數(shù),或本系列文章的第 1 部分和第 2 部分中給出的例子)。確保在建立請求時,將回調(diào)函數(shù)設(shè)置為 updatePage();要實(shí)現(xiàn)這種設(shè)置,可以將請求對象的 onreadystatechange 屬性設(shè)置為 updatePage()。

這段代碼就是 onreadystatechange 意義的一個確切展示 —— 每次請求的就緒狀態(tài)發(fā)生變化時,就調(diào)用 updatePage(),然后我們就可以看到一個警告了。圖 2 給出了一個調(diào)用這個函數(shù)的例子,其中就緒狀態(tài)為 1。

圖 2. 就緒狀態(tài) 1

您可以自己嘗試運(yùn)行這段代碼。將其放入 Web 頁面中,然后激活事件處理程序(單擊按鈕,在域之間按 tab 鍵切換焦點(diǎn),或者使用設(shè)置的任何方法來觸發(fā)請求)。這個回調(diào)函數(shù)會運(yùn)行多次 —— 每次就緒狀態(tài)都會改變 —— 您可以看到每個就緒狀態(tài)的警告。這是跟蹤請求所經(jīng)歷的各個階段的最好方法。

瀏覽器的不一致性

在對這個過程有一個基本的了解之后,請試著從幾個不同的瀏覽器中訪問您的頁面。您應(yīng)該會注意到各個瀏覽器如何處理這些就緒狀態(tài)并不一致。例如,在 Firefox 1.5 中,您會看到以下就緒狀態(tài):

·1
·2
·3
·4

這并不奇怪,因?yàn)槊總請求狀態(tài)都在這里表示出來了。然而,如果您使用 Safari 來訪問相同的應(yīng)用程序,就應(yīng)該看到 —— 或者看不到 —— 一些有趣的事情。下面是在 Safari 2.0.1 中看到的狀態(tài):

·2
·3
·4

Safari 實(shí)際上把第一個就緒狀態(tài)給丟棄了,也并沒有什么明顯的原因說明為什么要這樣做;不過這就是 Safari 的工作方式。這還說明了一個重要的問題:盡管在使用服務(wù)器上的數(shù)據(jù)之前確保請求的狀態(tài)為 4 是一個好主意,但是依賴于每個過渡期就緒狀態(tài)編寫的代碼的確會在不同的瀏覽器上得到不同的結(jié)果。

例如,在使用 Opera 8.5 時,所顯示的就緒狀態(tài)情況就更加糟糕了:

·3
·4

最后,Internet Explorer 會顯示如下狀態(tài):

·1
·2
·3
·4

如果您碰到請求方面的問題,這就是用來發(fā)現(xiàn)問題的 首要之處。最好的方式是在 Internet Explorer 和 Firefox 都進(jìn)行一下測試 —— 您會看到所有這 4 種狀態(tài),并可以檢查請求的每個狀態(tài)所處的情況。

接下來我們再來看一下響應(yīng)端的情況。

顯微鏡下的響應(yīng)數(shù)據(jù)

一旦我們理解在請求過程中發(fā)生的各個就緒狀態(tài)之后,接下來就可以來看一下 XMLHttpRequest 對象的另外一個方面了 —— responseText 屬性;叵胍幌略谏弦黄恼轮形覀兘榻B過的內(nèi)容,就可以知道這個屬性用來從服務(wù)器上獲取數(shù)據(jù)。一旦服務(wù)器完成對請求的處理之后,就可以將響應(yīng)請求數(shù)據(jù)所需要的任何數(shù)據(jù)放到請求的 responseText 中了。然后回調(diào)函數(shù)就可以使用這些數(shù)據(jù),如 清單 1 和 清單 4 所示。

清單 4. 使用服務(wù)器上返回的響應(yīng)

   function updatePage() {
     if (request.readyState == 4) {
       var newTotal = request.responseText;
       var totalSoldEl = document.getElementById("total-sold");
       var netProfitEl = document.getElementById("net-profit");
       replaceText(totalSoldEl, newTotal);

       /* 圖 out the new net profit */
       var boardCostEl = document.getElementById("board-cost");
       var boardCost = getText(boardCostEl);
       var manCostEl = document.getElementById("man-cost");
       var manCost = getText(manCostEl);
       var profitPerBoard = boardCost - manCost;
       var netProfit = profitPerBoard * newTotal;

       /* Update the net profit on the sales form */
       netProfit = Math.round(netProfit * 100) / 100;
       replaceText(netProfitEl, netProfit);
     }

清單 1 相當(dāng)簡單;清單 4 稍微有點(diǎn)復(fù)雜,但是它們在開始時都要檢查就緒狀態(tài),并獲取 responseText 屬性的值。

查看請求的響應(yīng)文本

與就緒狀態(tài)類似,responseText 屬性的值在整個請求的生命周期中也會發(fā)生變化。要查看這種變化,請使用如 清單 5 所示的代碼來測試請求的響應(yīng)文本,以及它們的就緒狀態(tài)。

清單 5. 測試 responseText 屬性

   function updatePage() {
     // Output the current ready state
     alert("updatePage() called with ready state of " + request.readyState +
           " and a response text of '" + request.responseText + "'");
     }

現(xiàn)在在瀏覽器中打開 Web 應(yīng)用程序,并激活您的請求。要更好地看到這段代碼的效果,請使用 Firefox 或 Internet Explorer,因?yàn)檫@兩個瀏覽器都可以報告出請求過程中所有可能的就緒狀態(tài)。例如在就緒狀態(tài) 2 中,就沒有定義 responseText (請參見 圖 3);如果 JavaScript 控制臺也已經(jīng)打開了,您就會看到一個錯誤。

圖 3. 就緒狀態(tài)為 2 的響應(yīng)文本

不過在就緒狀態(tài) 3 中,服務(wù)器已經(jīng)在 responseText 屬性中放上了一個值,至少在這個例子中是這樣(請參見 圖 4)。

圖 4. 就緒狀態(tài)為 3 的響應(yīng)文本

您會看到就緒狀態(tài)為 3 的響應(yīng)在每個腳本、每個服務(wù)器甚至每個瀏覽器上都是不一樣的。不過,這在調(diào)試應(yīng)用程序中依然是非常有用的。

獲取安全數(shù)據(jù)

所有的文檔和規(guī)范都強(qiáng)調(diào),只有在就緒狀態(tài)為 4 時數(shù)據(jù)才可以安全使用。相信我,當(dāng)就緒狀態(tài)為 3 時,您很少能找到無法從 responseText 屬性獲取數(shù)據(jù)的情況。然而,在應(yīng)用程序中將自己的邏輯依賴于就緒狀態(tài) 3 可不是什么好主意 —— 一旦您編寫了依賴于就緒狀態(tài) 3 的完整數(shù)據(jù)的的代碼,幾乎就要自己來負(fù)責(zé)當(dāng)時的數(shù)據(jù)不完整問題了。

比較好的做法是向用戶提供一些反饋,說明在處于就緒狀態(tài) 3 時,很快就會有響應(yīng)了。盡管使用 alert() 之類的函數(shù)顯然不是什么好主意 —— 使用 Ajax 然后使用一個警告對話框來阻塞用戶顯然是錯誤的 —— 不過您可以在就緒狀態(tài)發(fā)生變化時更新表單或頁面中的域。例如,對于就緒狀態(tài) 1 來說要將進(jìn)度指示器的寬度設(shè)置為 25%,對于就緒狀態(tài) 2 來說要將進(jìn)度指示器的寬度設(shè)置為 50%,對于就緒狀態(tài) 3 來說要將進(jìn)度指示器的寬度設(shè)置為 75%,當(dāng)就緒狀態(tài)為 4 時將進(jìn)度指示器的寬度設(shè)置為 100%(完成)。

當(dāng)然,正如您已經(jīng)看到的一樣,這種方法非常聰明,但它是依賴于瀏覽器的。在 Opera 上,您永遠(yuǎn)都不會看到前兩個就緒狀態(tài),而在 Safari 上則沒有第一個(1)。由于這個原因,我將這段代碼留作練習(xí),而沒有在本文中包括進(jìn)來。

現(xiàn)在應(yīng)該來看一下狀態(tài)代碼了。

深入了解 HTTP 狀態(tài)代碼

有了就緒狀態(tài)和您在 Ajax 編程技術(shù)中學(xué)習(xí)到的服務(wù)器的響應(yīng),您就可以為 Ajax 應(yīng)用程序添加另外一級復(fù)雜性了 —— 這要使用 HTTP 狀態(tài)代碼。這些代碼對于 Ajax 來說并沒有什么新鮮。從 Web 出現(xiàn)以來,它們就已經(jīng)存在了。在 Web 瀏覽器中您可能已經(jīng)看到過幾個狀態(tài)代碼:

·401:未經(jīng)授權(quán)
·403:禁止
·404:沒找到

您可以找到更多的狀態(tài)代碼(完整清單請參見 參考資料)。要為 Ajax 應(yīng)用程序另外添加一層控制和響應(yīng)(以及更為健壯的錯誤處理)機(jī)制,您需要適當(dāng)?shù)夭榭凑埱蠛晚憫?yīng)中的狀態(tài)代碼。

200:一切正常

在很多 Ajax 應(yīng)用程序中,您將看到一個回調(diào)函數(shù),它負(fù)責(zé)檢查就緒狀態(tài),然后繼續(xù)利用從服務(wù)器響應(yīng)中返回的數(shù)據(jù),如 清單 6 所示。

清單 6. 忽略狀態(tài)代碼的回調(diào)函數(shù)

   function updatePage() {
     if (request.readyState == 4) {
       var response = request.responseText.split("|");
       document.getElementById("order").value = response[0];
       document.getElementById("address").innerHTML =
         response[1].replace(/\n/g, "<br />");
     }
   }

這對于 Ajax 編程來說證明是一種短視而錯誤的方法。如果腳本需要認(rèn)證,而請求卻沒有提供有效的證書,那么服務(wù)器就會返回諸如 403 或 401 之類的錯誤代碼。然而,由于服務(wù)器對請求進(jìn)行了應(yīng)答,因此就緒狀態(tài)就被設(shè)置為 4(即使應(yīng)答并不是請求所期望的也是如此)。最終,用戶沒有獲得有效數(shù)據(jù),當(dāng) JavaScript 試圖使用不存在的服務(wù)器數(shù)據(jù)時就可能會出現(xiàn)嚴(yán)重的錯誤。

它花費(fèi)了最小的努力來確保服務(wù)器不但完成了一個請求,而且還返回了一個 “一切良好” 的狀態(tài)代碼。這個代碼是 "200",它是通過 XMLHttpRequest 對象的 status 屬性來報告的。為了確保服務(wù)器不但完成了一個請求,而且還報告了一個 OK 狀態(tài),請在您的回調(diào)函數(shù)中添加另外一個檢查功能,如 清單 7 所示。

清單 7. 檢查有效狀態(tài)代碼

   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, "<br />");
       } else
         alert("status is " + request.status);
     }
   }

通過添加這幾行代碼,您就可以確認(rèn)是否存在問題,用戶會看到一個有用的錯誤消息,而不僅僅是看到一個由斷章取義的數(shù)據(jù)所構(gòu)成的頁面,而沒有任何解釋。

重定向和重新路由

在深入介紹有關(guān)錯誤的內(nèi)容之前,我們有必要來討論一下有關(guān)一個在使用 Ajax 時 并不需要 關(guān)心的問題 —— 重定向。在 HTTP 狀態(tài)代碼中,這是 300 系列的狀態(tài)代碼,包括:

·301:永久移動
·302:找到(請求被重新定向到另外一個 URL/URI 上)
·305:使用代理(請求必須使用一個代理來訪問所請求的資源)

Ajax 程序員可能并不太關(guān)心有關(guān)重定向的問題,這是由于兩方面的原因:

·首先,Ajax 應(yīng)用程序通常都是為一個特定的服務(wù)器端腳本、servlet 或應(yīng)用程序而編寫的。對于那些您看不到就消失了的組件來說,Ajax 程序員就不太清楚了。因此有時您會知道資源已經(jīng)移動了(因?yàn)槟苿恿怂,或者通過某種手段移動了它),接下來要修改請求中的 URL,并且不會再碰到這種結(jié)果了。
更為重要的一個原因是:Ajax 應(yīng)用程序和請求都是封裝在沙盒中的。這就意味著提供生成 Ajax 請求的 Web 頁面的域必須是對這些請求進(jìn)行響應(yīng)的域。因此 ebay.com 所提供的 Web 頁面就不能對一個在 amazon.com 上運(yùn)行的腳本生成一個 Ajax 風(fēng)格的請求;在 ibm.com 上的 Ajax 應(yīng)用程序也無法對在 netbeans.org 上運(yùn)行的 servlets 發(fā)出請求。
·結(jié)果是您的請求無法重定向到其他服務(wù)器上,而不會產(chǎn)生安全性錯誤。在這些情況中,您根本就不會得到狀態(tài)代碼。通常在調(diào)試控制臺中都會產(chǎn)生一個 JavaScript 錯誤。因此,在對狀態(tài)代碼進(jìn)行充分的考慮之后,您就可以完全忽略重定向代碼的問題了。

結(jié)果是您的請求無法重定向到其他服務(wù)器上,而不會產(chǎn)生安全性錯誤。在這些情況中,您根本就不會得到狀態(tài)代碼。通常在調(diào)試控制臺中都會產(chǎn)生一個 JavaScript 錯誤。因此,在對狀態(tài)代碼進(jìn)行充分的考慮之后,您就可以完全忽略重定向代碼的問題了。

錯誤

一旦接收到狀態(tài)代碼 200 并且意識到可以很大程度上忽略 300 系列的狀態(tài)代碼之后,所需要擔(dān)心的唯一一組代碼就是 400 系列的代碼了,這說明了不同類型的錯誤。回頭再來看一下 清單 7,并注意在對錯誤進(jìn)行處理時,只將少數(shù)常見的錯誤消息輸出給用戶了。盡管這是朝正確方向前進(jìn)的一步,但是要告訴從事應(yīng)用程序開發(fā)的用戶和程序員究竟發(fā)生了什么問題,這些消息仍然是沒有太大用處的。

首先,我們要添加對找不到的頁的支持。實(shí)際上這在大部分產(chǎn)品系統(tǒng)中都不應(yīng)該出現(xiàn),但是在測試腳本位置發(fā)生變化或程序員輸入了錯誤的 URL 時,這種情況并不罕見。如果您可以自然地報告 404 錯誤,就可以為那些困擾不堪的用戶和程序員提供更多幫助。例如,如果服務(wù)器上的一個腳本被刪除了,我們就可以使用 清單 7 中的代碼,這樣用戶就會看到一個如 圖 5 所示的非描述性錯誤。

邊界情況和困難情況

看到現(xiàn)在,一些新手程序員就可能會這究竟是要討論什么內(nèi)容。有一點(diǎn)事實(shí)大家需要知道:只有不到 5% 的 Ajax 請求需要使用諸如 2、3 之類的就緒狀態(tài)和諸如 403 之類的狀態(tài)代碼(實(shí)際上,這個比率可能更接近于 1% 甚至更少)。這些情況非常重要,稱為 邊界情況(edge case) —— 它們只會在一些非常特殊的情況下發(fā)生,其中遇到的都是最奇特的問題。雖然這些情況并不普遍,但是這些邊界情況卻占據(jù)了大部分用戶所碰到的問題的 80%!

對于典型的用戶來說,應(yīng)用程序 100 次都是正常工作的這個事實(shí)通常都會被忘記,然而應(yīng)用程序只要一次出錯就會被他們清楚地記住。如果您可以很好地處理邊界情況(或困難情況),就可以為再次訪問站點(diǎn)的用戶提供滿意的回報。

圖 5. 常見錯誤處理

用戶無法判斷問題究竟是認(rèn)證問題、沒找到腳本(此處就是這種情況)、用戶錯誤還是代碼中有些地方產(chǎn)生了問題。添加一些簡單的代碼可以讓這個錯誤更加具體。請參照 清單 8,它負(fù)責(zé)處理沒找到的腳本或認(rèn)證發(fā)生錯誤的情況,在出現(xiàn)這些錯誤時都會給出具體的消息。

清單 8. 檢查有效狀態(tài)代碼

   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, "<br />");
       } else if (request.status == 404) {
         alert ("Requested URL is not found.");
       } else if (request.status == 403) {
         alert("Access denied.");
       } else
         alert("status is " + request.status);
     }
   }

雖然這依然相當(dāng)簡單,但是它的確多提供了一些有用的信息。圖 6 給出了與 圖 5 相同的錯誤,但是這一次錯誤處理代碼向用戶或程序員更好地說明了究竟發(fā)生了什么。

圖 6. 特殊錯誤處理

在我們自己的應(yīng)用程序中,可以考慮在發(fā)生認(rèn)證失敗的情況時清除用戶名和密碼,并向屏幕上添加一條錯誤消息。我們可以使用類似的方法來更好地處理找不到腳本或其他 400 類型的錯誤(例如 405 表示不允許使用諸如發(fā)送 HEAD 請求之類不可接受的請求方法,而 407 則表示需要進(jìn)行代理認(rèn)證)。然而不管采用哪種選擇,都需要從對服務(wù)器上返回的狀態(tài)代碼開始入手進(jìn)行處理。

其他請求類型

如果您真希望控制 XMLHttpRequest 對象,可以考慮最后實(shí)現(xiàn)這種功能 —— 將 HEAD 請求添加到指令中。在前兩篇文章中,我們已經(jīng)介紹了如何生成 GET 請求;在馬上就要發(fā)表的一篇文章中,您會學(xué)習(xí)有關(guān)使用 POST 請求將數(shù)據(jù)發(fā)送到服務(wù)器上的知識。不過本著增強(qiáng)錯誤處理和信息搜集的精神,您應(yīng)該學(xué)習(xí)如何生成 HEAD 請求。

生成請求

實(shí)際上生成 HEAD 請求非常簡單;您可以使用 "HEAD"(而不是 "GET" 或 "POST")作為第一個參數(shù)來調(diào)用 open() 方法,如 清單 9 所示。

清單 9. 使用 Ajax 生成一個 HEAD 請求

   function getSalesData() {
     createRequest();
     var url = "/boards/servlet/UpdateBoardSales";
     request.open("HEAD", url, true);
     request.onreadystatechange = updatePage;
     request.send(null);
   }

當(dāng)您這樣生成一個 HEAD 請求時,服務(wù)器并不會像對 GET 或 POST 請求一樣返回一個真正的響應(yīng)。相反,服務(wù)器只會返回資源的 頭(header),這包括響應(yīng)中內(nèi)容最后修改的時間、請求資源是否存在和很多其他有用信息。您可以在服務(wù)器處理并返回資源之前使用這些信息來了解有關(guān)資源的信息。

對于這種請求您可以做的最簡單的事情就是簡單地輸出所有的響應(yīng)頭的內(nèi)容。這可以讓您了解通過 HEAD 請求可以使用什么。清單 10 提供了一個簡單的回調(diào)函數(shù),用來輸出從 HEAD 請求中獲得的響應(yīng)頭的內(nèi)容。

清單 10. 輸出從 HEAD 請求中獲得的響應(yīng)頭的內(nèi)容

   function updatePage() {
     if (request.readyState == 4) {
       alert(request.getAllResponseHeaders());
     }
   }

請參見 圖 7,其中顯示了從一個向服務(wù)器發(fā)出的 HEAD 請求的簡單 Ajax 應(yīng)用程序返回的響應(yīng)頭。

您可以單獨(dú)使用這些頭(從服務(wù)器類型到內(nèi)容類型)在 Ajax 應(yīng)用程序中提供其他信息或功能。

檢查 URL

您已經(jīng)看到了當(dāng) URL 不存在時應(yīng)該如何檢查 404 錯誤。如果這變成一個常見的問題 —— 可能是缺少了一個特定的腳本或 servlet —— 那么您就可能會希望在生成完整的 GET 或 POST 請求之前來檢查這個 URL。要實(shí)現(xiàn)這種功能,生成一個 HEAD 請求,然后在回調(diào)函數(shù)中檢查 404 錯誤;清單 11 給出了一個簡單的回調(diào)函數(shù)。

清單 11. 檢查某個 URL 是否存在

   function updatePage() {
     if (request.readyState == 4) {
       if (request.status == 200) {
         alert("URL exists");
       } else if (request.status == 404) {
         alert("URL does not exist.");
       } else {
         alert("Status is: " + request.status);
       }
     }
   }

誠實(shí)地說,這段代碼的價值并不太大。服務(wù)器必須對請求進(jìn)行響應(yīng),并構(gòu)造一個響應(yīng)來填充內(nèi)容長度的響應(yīng)頭,因此并不能節(jié)省任何處理時間。另外,這花費(fèi)的時間與生成請求并使用 HEAD 請求來查看 URL 是否存在所需要的時間一樣多,因?yàn)樗墒褂?GET 或 POST 的請求,而不僅僅是如 清單 7 所示一樣來處理錯誤代碼。不過,有時確切地了解目前什么可用也是非常有用的;您永遠(yuǎn)不會知道何時創(chuàng)造力就會迸發(fā)或者何時需要 HEAD 請求!

有用的 HEAD 請求

您會發(fā)現(xiàn) HEAD 請求非常有用的一個領(lǐng)域是用來查看內(nèi)容的長度或內(nèi)容的類型。這樣可以確定是否需要發(fā)回大量數(shù)據(jù)來處理請求,和服務(wù)器是否試圖返回二進(jìn)制數(shù)據(jù),而不是 HTML、文本或 XML(在 JavaScript 中,這 3 種類型的數(shù)據(jù)都比二進(jìn)制數(shù)據(jù)更容易處理)。

在這些情況中,您只使用了適當(dāng)?shù)念^名,并將其傳遞給 XMLHttpRequest 對象的 getResponseHeader() 方法。因此要獲取響應(yīng)的長度,只需要調(diào)用 request.getResponseHeader("Content-Length");。要獲取內(nèi)容類型,請使用 request.getResponseHeader("Content-Type");。

在很多應(yīng)用程序中,生成 HEAD 請求并沒有增加任何功能,甚至可能會導(dǎo)致請求速度變慢(通過強(qiáng)制生成一個 HEAD 請求來獲取有關(guān)響應(yīng)的數(shù)據(jù),然后在使用一個 GET 或 POST 請求來真正獲取響應(yīng))。然而,在出現(xiàn)您不確定有關(guān)腳本或服務(wù)器端組件的情況時,使用 HEAD 請求可以獲取一些基本的數(shù)據(jù),而不需要對響應(yīng)數(shù)據(jù)真正進(jìn)行處理,也不需要大量的帶寬來發(fā)送響應(yīng)。

結(jié)束語

對于很多 Ajax 和 Web 程序員來說,本文中介紹的內(nèi)容似乎是太高級了。生成 HEAD 請求的價值是什么呢?到底在什么情況下需要在 JavaScript 中顯式地處理重定向狀態(tài)代碼呢?這些都是很好的問題;對于簡單的應(yīng)用程序來說,答案是這些高級技術(shù)的價值并不是非常大。

然而,Web 已經(jīng)不再是只需實(shí)現(xiàn)簡單應(yīng)用程序的地方了;用戶已經(jīng)變得更加高級,客戶期望能夠獲得更好的穩(wěn)定性、更高級的錯誤報告,如果應(yīng)用程序有 1% 的時間停機(jī),那么經(jīng)理就可能會因此而被解雇。

因此您的工作就不能僅僅局限于簡單的應(yīng)用程序了,而是需要更深入理解 XMLHttpRequest。

·如果您可以考慮各種就緒狀態(tài) —— 并且理解了這些就緒狀態(tài)在不同瀏覽器之間的區(qū)別 —— 就可以快速調(diào)試應(yīng)用程序了。您甚至可以基于就緒狀態(tài)而開發(fā)一些創(chuàng)造性的功能,并向用戶和客戶回報請求的狀態(tài)。
·如果您要對狀態(tài)代碼進(jìn)行控制,就可以設(shè)置應(yīng)用程序來處理腳本錯誤、非預(yù)期的響應(yīng)以及邊緣情況。結(jié)果是應(yīng)用程序在所有的時間都可以正常工作,而不僅僅是只能一切都正常的情況下才能運(yùn)行。
·增加這種生成 HEAD 請求的能力,檢查某個 URL 是否存在,以及確認(rèn)某個文件是否被修改過,這樣就可以確保用戶可以獲得有效的頁面,用戶所看到的信息都是最新的,(最重要的是)讓他們驚訝這個應(yīng)用程序是如何健壯和通用。
本文的目的并非是要讓您的應(yīng)用程序顯得十分華麗,而是幫助您去掉黃色聚光燈后重點(diǎn)昭顯文字的美麗,或者外觀更像桌面一樣。盡管這些都是 Ajax 的功能(在后續(xù)幾篇文章中就會介紹),不過它們卻像是蛋糕表面的一層奶油。如果您可以使用 Ajax 來構(gòu)建一個堅實(shí)的基礎(chǔ),讓應(yīng)用程序可以很好地處理錯誤和問題,用戶就會返回您的站點(diǎn)和應(yīng)用程序。在接下來的文章中,我們將添加這種直觀的技巧,這會讓客戶興奮得發(fā)抖。(認(rèn)真地說,您一定不希望錯過下一篇文章。

出處:IBM developerWorks
責(zé)任編輯:moby

上一頁 使用 JavaScript 和 Ajax 發(fā)出異步請求 下一頁 利用 DOM 進(jìn)行 Web 響應(yīng)

◎進(jìn)入論壇網(wǎng)絡(luò)編程版塊參加討論

相關(guān)文章
ajax代理程序自動判斷字符編碼
如何使用ajax開發(fā)web應(yīng)用程序
AJAX開發(fā)簡略
基于 Ajax 的無限級菜單
基于Ajax的應(yīng)用程序架構(gòu)匯總
關(guān)鍵字搜索 常規(guī)搜索 推薦文檔
熱門搜索:CSS Fireworks 設(shè)計比賽 網(wǎng)頁制作 web標(biāo)準(zhǔn) 用戶體驗(yàn) UE photoshop Dreamweaver Studio8 Flash 手繪 CG
站點(diǎn)最新 站點(diǎn)最新列表
周大!熬•自然”設(shè)計大賽開啟
國際體驗(yàn)設(shè)計大會7月將在京舉行
中國國防科技信息中心標(biāo)志征集
云計算如何讓安全問題可控
云計算是多數(shù)企業(yè)唯一擁抱互聯(lián)網(wǎng)的機(jī)會
阿里行云
云手機(jī)年終巨獻(xiàn),送禮標(biāo)配299起
阿里巴巴CTO王堅的"云和互聯(lián)網(wǎng)觀"
1499元買真八核 云OS雙蛋大促
首屆COCO桌面手機(jī)主題設(shè)計大賽
欄目最新 欄目最新列表
淺談JavaScript編程語言的編碼規(guī)范
如何在illustrator中繪制臺歷
Ps簡單繪制一個可愛的鉛筆圖標(biāo)
數(shù)據(jù)同步算法研究
用ps作簡單的作品展示頁面
CSS定位機(jī)制之一:普通流
25個最佳最閃亮的Eclipse開發(fā)項(xiàng)目
Illustrator中制作針線縫制文字效果
Photoshop制作印刷凹凸字體
VS2010中創(chuàng)建自定義SQL Rule
>> 分頁 首頁 前頁 后頁 尾頁 頁次:3/51個記錄/頁 轉(zhuǎn)到 頁 共5個記錄

藍(lán)色理想版權(quán)申明:除部分特別聲明不要轉(zhuǎn)載,或者授權(quán)我站獨(dú)家播發(fā)的文章外,大家可以自由轉(zhuǎn)載我站點(diǎn)的原創(chuàng)文章,但原作者和來自我站的鏈接必須保留(非我站原創(chuàng)的,按照原來自一節(jié),自行鏈接)。文章版權(quán)歸我站和作者共有。

轉(zhuǎn)載要求:轉(zhuǎn)載之圖片、文件,鏈接請不要盜鏈到本站,且不準(zhǔn)打上各自站點(diǎn)的水印,亦不能抹去我站點(diǎn)水印。

特別注意:本站所提供的攝影照片,插畫,設(shè)計作品,如需使用,請與原作者聯(lián)系,版權(quán)歸原作者所有,文章若有侵犯作者版權(quán),請與我們聯(lián)系,我們將立即刪除修改。

您的評論
用戶名:  口令:
說明:輸入正確的用戶名和密碼才能參與評論。如果您不是本站會員,你可以注冊 為本站會員。
注意:文章中的鏈接、內(nèi)容等需要修改的錯誤,請用報告錯誤,以利文檔及時修改。
不評分 1 2 3 4 5
注意:請不要在評論中含與內(nèi)容無關(guān)的廣告鏈接,違者封ID
請您注意:
·不良評論請用報告管理員,以利管理員及時刪除。
·尊重網(wǎng)上道德,遵守中華人民共和國的各項(xiàng)有關(guān)法律法規(guī)
·承擔(dān)一切因您的行為而直接或間接導(dǎo)致的民事或刑事法律責(zé)任
·本站評論管理人員有權(quán)保留或刪除其管轄評論中的任意內(nèi)容
·您在本站發(fā)表的作品,本站有權(quán)在網(wǎng)站內(nèi)轉(zhuǎn)載或引用
·參與本評論即表明您已經(jīng)閱讀并接受上述條款
推薦文檔 | 打印文檔 | 評論文檔 | 報告錯誤  
專業(yè)書推薦 更多內(nèi)容
網(wǎng)站可用性測試及優(yōu)化指南
《寫給大家看的色彩書1》
《跟我去香港》
眾妙之門—網(wǎng)站UI 設(shè)計之道
《Flex 4.0 RIA開發(fā)寶典》
《贏在設(shè)計》
犀利開發(fā)—jQuery內(nèi)核詳解與實(shí)踐
作品集 更多內(nèi)容

雜⑦雜⑧ Gold NORMANA V2