5 個 Ajax 最佳實踐

 

本文所介紹的 5 個最佳實踐,可以應用到您 web 應用程序 Ajax 開發工作中:

  1. 最小化調用
  2. 讓數據變小
  3. 預加載組件
  4. 輕鬆實現錯誤處理
  5. 使用現有工具

這些最佳實踐,有助於您編寫更加健壯的 JavaScript 代碼,並使您的 Ajax 代碼執行的更快,這可以給用戶帶來益處。

Ajax 概述

Ajax 用於描述存在已久的技術:JavaScript 代碼、XML、以及能夠通過 HTTP 進行異步調用的對象。Ajax 常用於避免提交併重新加載整個網頁,特別是在用戶執行的動作不需要重新加載整個網頁時。

在過去幾年中,支持 Ajax 的站點在不斷的完善,作爲此類站點的開發工具,Ajax 的應用也越來越廣泛。使用本文的實踐通過 Ajax 和 JavaScript 來構建更優的 web 應用程序。


最小化調用

聽起來可能很明顯,但使用 Ajax 技術提高您的 web 應用程序性能,惟一能做的就是最小化您的調用數量。

最小化調用數量的方法之一是將大量調用合併成少量調用。如果數據量相對小(見 “讓數據變小”),那麼在大多數網絡中,主要問題就在於延遲。延遲是瀏覽器真正獲取服務器與服務的連接所需的時間,有時它會佔去大部分連接時間。用戶所感受到的總延遲由幾個部分組成,包括瀏覽器的緩存設置、DNS 客戶端、以及物理連接。

沒有簡易公式或代碼片段供您閱讀來了解如何減小 web 應用程序調用。然而,只需一個簡單的練習,就可以演示如何對從客戶端到服務器的 Ajax 調用數量進行控制。考慮購買二手摩托車的 web 應用程序(見圖 1)。


圖 1. 搜索二手摩托車的示例 web 頁面
截屏中有構造、型號、年份、以及郵編字段的下拉按鈕。

首先,用戶選擇摩托車的年份。然後,用戶選擇摩托車的構造。最後用戶選擇摩托車的型號。從始至終,Ajax 一直在後臺運行,更新 web 應用程序中的下拉框來爲用戶過濾清單,以方便用戶選擇。

要開始這一練習,首先要爲客戶端及服務器創建一個簡單圖表(有一個文本框)。然後爲您瀏覽器進行的 Ajax 調用畫線,來從服務器獲取用戶數據,如圖 2 所示。


圖 2. 繪製 Ajax 調用
從瀏覽器及服務器中延伸出虛線,在用於品牌、型號與庫存的兩個之間採用實線。

可通過將對品牌和型號進行的調用合併到一個調用中,來優化設計。不是對品牌進行一次調用,然後針對型號進行另一次調用,而是對型號進行緩存,這樣,當用戶選擇品牌時,新代碼只檢索緩存中可用的型號列表。從本地緩存中獲取數據要比從服務獲取相同數據快得多。迴避額外的服務調用,您就可以避免服務調用的延遲。新的通信情況如圖 3 所示。


圖 3. 合併獲取品牌調用與獲取型號調用後的 Ajax 調用
從瀏覽器及服務器中延伸出虛線,其中有兩條實線;一個用於品牌及型號,另一個用於庫存。

到目前爲止,新設計在瀏覽器與服務器之間的通信中去掉了一個調用。您可利用清單 1 中的代碼進一步減少調用數量,其中的一些關鍵行可用於存儲在數組中檢索到的數據,供以後查找使用。


清單 1. 在緩存中存儲本地數據
				
var choices = new Array();

function fillChoiceBoxes(year) {

    // see resources for links to dojo toolkit...
    if (dojo.indexOf(choices, year) == -1) {
        // go get the         
    } else {
        // make the ajax call and fill the choices.    
        choices[year] = result; // result of ajax call.
    }

    // calling a function to fill the values...
    fillSelect(dojo.byId('makes'), choices[year]);

}

如果用戶在反覆考慮兩個不同的型號,web 應用程序會使用本地緩存數據,而不是發起附加服務調用。僅緩存靜態數據 —— 至少是在用戶會話持續階段。不要因爲緩存了不應緩存的數據,而引起一系列問題。

正如本例所展示的,可通過減少客戶端與服務器之間的交互次數,以及在可能的情況下緩存數據,來最小化調用。


讓您的數組變得很小

爲提高數據處理性能,需要讓服務器與客戶端之間出傳輸的數據儘量的小。爲高效地完成這一任務,必須已經控制了從服務層,到能夠指定從服務到客戶端的消息類型的部分。

有充足的理由證明,XML 適合作爲客戶端到服務器的通用消息格式。理由之一是存在足夠多的庫或者框架,來用於 XML 序列化。

然而,當與 JavaScript Serialized Object Notation(JSON)對比時,XML 顯得很冗長,而前者更加簡明。目前已經有很多可以將您的消息方便地構建成 JSON 格式的庫,這樣就可以通過 JSON 的方式將數據從服務端傳送的客戶端。

很多客戶端庫,比如 Dojo Toolkit,允許定義服務所採用的傳輸格式。如果服務響應使用 JSON,可通過提供一個參數來使用相同的客戶端對象。

仔細研究一下清單 2 中的代碼,其展示了使用 XML 的摩托車對象的表示。


清單 2. 使用 XML 的摩托車數據
				
<motorcycle>
  <year>2010</year>
  <make>Motocool</make>
  <model>Uberfast</model>
</motorcycle>

現在來看一下清單 3,其展示了使用 JSON 的相同數據。注意,它的代碼量減少了大約 25%(如果去掉空格)。


清單 3. 使用 JSON 的摩托車數據
				
{ 
"motorcycle" : { 
    "year" : "2010", 
    "make" : "Motocool", 
    "model" : "Uberfast"
    }
}

由於數據量變小了,不僅減少了從服務端到客戶端的傳輸時間,而且,由於字符串的減小還節省了解析時間。

在設計需要傳輸的數據時,其所包含的字符越少越好。


預加載組件

可通過在 Ajax 調用中加載 JavaScript 文件與圖像之類的組件,來充分利用瀏覽器的緩存。需要注意的是,預加載 JavaScript 文件和圖像,僅對那些開啓緩存功能的用戶有益,不過大多數用戶的瀏覽器都開啓了緩存功能。

想要預加載外部 JavaScript 文件,將 JavaScript 文件包面中,但是,只有當該頁面很小而且僅想優化少量資源時,才適合採用這一方式。例如,當您有一個將工作流引入用戶的相對輕量級的頁面時,預加載非常有用。考慮 最小化調用 部分中購買摩托車的例子。可在流的早期頁面中預加載用於包含下拉框的頁面的、包含全部 Ajax 代碼的 JavaScript 代碼。

如果要用 Ajax 調用的方法更新圖片,預加載圖像會提供很大方便。預加載圖像後,當用戶將鼠標移動到元素時、從下拉框中進行選擇時、或者單擊按鈕時,不必等待瀏覽器對圖像進行檢索。即使 Ajax 以異步方式發生,也需要花費一些時間將圖像從服務器傳送到客戶端,並且在圖像全部下載完畢之前,它不會在客戶端中顯示。

在清單 4 所展示的例子中,用戶進行從清單中選擇摩托車這一操作時,所採用的圖像就是使用標準 JavaScript 代碼預加載的。


清單 4. 使用標準 JavaScript 代碼預加載圖像
				
<html>
<head><title>Preload example</title></head>
<body>
<!-- web page... -->
<script type="text/javascript" language="javascript">
    var img = new Image();
    img.src = "http://path/to/motocool.jpg";
</script>
</body>
</html>

爲頁面預加載圖像時,JavaScript 的位置很重要。您一定不希望因爲在 HTML 中加入了 JavaScript 代碼而影響頁面的加載速度。一般的規則是,可將 <script> 元素當中的 JavaScript 代碼放到 HTML 頁面的最後部分,因爲在考慮可同時下載多少資源時,瀏覽器的能力就相對有限了。如果可能,將腳本加到 HTML 頁面的最後部分,來幫助瀏覽器更快速加載圖像和其他資源。

在 HTML 5 中,可使用 <script> 標記的新 async 屬性。這將告訴瀏覽器異步運行 JavaScript 代碼,這樣,它可以在頁面中運行其他東西時執行。


輕鬆處理錯誤

在 JavaScript 代碼中定義的每個函數,都要假設會有惡意輸入發生,因爲,防禦性能強的代碼比使用 try... catch 語句所編寫的代碼更善於處理錯誤。例如,如果想使用 JavaScript 函數來根據用戶輸入進行計算,在計算前檢查輸入,如清單 5 所示。


清單 5. 檢查用戶輸入
				
function caculateDistance(source,dest) {
    if (! isNaN(source) || ! isNan(dest)) {
        dojo.byId("errors").innerHTML = "Please provide a valid number.";
    }
}

即使代碼具有防禦能力,在適當時候,也可使用 try... catch 語句與錯誤回調。清單 6 演示了在 JavaScript 代碼中使用 try... catch 語句來捕獲錯誤。


清單 6. 使用 try... catch 語句來處理錯誤
				
function calculateDistance(source,dest) {
    try {
        // do some calculations...
    } catch (error) {
        dojo.byId("errors").innerHTML = "An error occurred while adding the numbers";
    }
}

清單 7 演示了在調用 Dojo Toolkit 中所提供的 xhrGet() 方法時,對錯誤回調的使用。錯誤參數是可選的,因此可以很容易地跳過錯誤處理器的定義。


清單 7. 使用具有 xhrGet() 的錯誤回調
				
var args = {
    url: "/moin_static185/js/dojo/trunk/dojo/../dojo/NoSuchFile",
    handleAs: "text",
    preventCache: true,
    load: function(data) {
        // do something when successful...
    },
    error: function(error) {
        dojo.byId("errors").innerHTML = "An error occurred while getting the data..";
    }
}
var ajx = dojo.xhrGet(args);

如何處理頁面上的錯誤,這既是個業務問題,也是個技術問題。要詢問客戶,在出現問題時,想讓用戶看到什麼消息,因爲任何展示給用戶的消息,都會對業務造成影響。適當時,客戶能夠幫助提供在出現異常時有效的默認處理方式。

最後,不要象清單 8 中那樣,在 JavaScript 提示對話框中顯示錯誤描述。您的用戶不是軟件工程師,因此,這類提示信息對於用戶來說沒有任何意義。除了不要爲用戶提供無意義的信息之外,提示對話框應當要求客戶取消該對話框,來返回 web 頁面。


清單 8. 在錯誤處理中避免 JavaScript 提示對話框
				
function calculateDistance(source,dest) {
	try {
		// do some calculations...
	} catch (error) {
                // Bad:
		// alert(error.message);
                // Better:
                dojo.byId("errors").innerHTML = 
                    "An error occurred while calculating data...";
	}
}


使用現有工具

最後,作爲最佳實踐之一,要儘量避免 Not Invented Here(NIH)綜合症。通過使用現有工具(框架與平臺),可有效利用其資源。大多數成熟的技術人員,會使用已在多個平臺上測試過,並具有跨瀏覽器兼容性的工具。現有工具的大部分特性可用於部署到您自己的項目中。

很多現有的優秀工具,除了能提供 Ajax 調用之外,還能支持很多其他函數與特性,比如動畫。表 1 中列出了其中一些工具。


表 1. 爲 Ajax 調用提供方法的 JavaScript 工具
工具 描述
Dojo Toolkit Dojo Toolkit 是免費的 JavaScript 工具套件。它爲一般 web 頁面提供 Ajax 調用方法,以及 Representational State Transfer(REST)服務。Dojo Toolkit 方法支持 XML、JSON、以及明文的消息格式。
Google Web Toolkit(GWT)Designer Google 最近收購了 Instantiations Developer Tools 並重新推出一系列免費產品。其中之一是 GWT Designer,可將其安裝到現有的 Eclipse 中。可利用設計器來輔助構建採用 GWT 的接口。GWT 用於構建採用 Ajax 的複雜 web 應用程序,這使得 web 應用程序可以如同本地應用程序一樣複雜。與 Rich Ajax Platform(RAP)類似,GWT 不單單是一個 JavaScript 框架,而且還是編譯到 Ajax-enabled HTML 中的基於 Java™ 的工具集。
jQuery jQuery 是另一個 JavaScript 庫,它能提供全套的 Ajax 功能。jQuery 還支持不同的消息格式以及其他基於 Ajax 的方法,比如 getScript(),它可用於下載並執行 JavaScript 文件(是 預載組件 最佳實踐的起源)。
Prototype Prototype 也是個 JavaScript 框架,可用於方便地發起 Ajax 調用。利用 Ajax.PeriodicalUpdater 之類的方法,可基於策略來更新 Ajax 頁面中的值,這樣,就可爲運行時間較長的服務進程實現進度條或者其他方式的控制。
Rich Ajax Platform (RAP)

與表中列出的其他框架不同,RAP 是個完整的平臺,使得您可以利用 Eclipse 集成開發環境(IDE)和 Java(不是腳本)代碼來構建 Ajax-enabled 的更優站點。類似於構建一個 Swing 或者 Standard Widget Toolkit(SWT)應用程序。對於不想使用複雜的 HTML、CSS、以及 JavaScript 代碼的 Java 程序員來說,RAP 之類的平臺工具是非常不錯的選擇。

RAP 文檔提示說不要將其作爲插件安裝到現有 Eclipse 中。然而,可從 Eclipse 站點(見 參考資料)下載 Eclipse for Rich Client Platform(RCP)and RAP Developers 包,並將其安裝到單獨的位置。相關備忘單展示瞭如果導入示例項目。


結束語

在 web 應用程序中使用 Ajax ,可爲您的用戶提供整潔的 web 應用程序界面。Ajax 已對整個 HTML 頁面的傳遞提供了一些優化,然而,通過了解本文中描述的最佳實踐,可幫助您構建更加優化的 Ajax 應用程序。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章