一 Ajax技術與原理
1.1 Ajax簡介
AJAX = Asynchronous JavaScript and XML(異步的 JavaScript 和 XML)。
AJAX 不是新的編程語言,而是一種使用現有標准的新方法。
AJAX 是與服務器交換數據並更新部分網頁的藝術,在不重新加載整個頁面的情況下。
1.2 Ajax所包含的技術
大家都知道ajax並非一種新的技術,而是幾種原有技術的結合體。它由下列技術組合而成。
1.使用CSS和XHTML來表示。
2. 使用DOM模型來交互和動態顯示。
3.使用XMLHttpRequest來和服務器進行異步通信。
4.使用javascript來綁定和調用。
AJAX 的核心是 XMLHttpRequest 對象。
不同的瀏覽器創建 XMLHttpRequest 對象的方法是有差異的。
IE 瀏覽器使用 ActiveXObject,而其他的瀏覽器使用名為 XMLHttpRequest 的 JavaScript 內建對象
1.3 Ajax的工作原理
Ajax的工作原理相當於在用戶和服務器之間加了—個中間層(AJAX引擎),使用戶操作與服務器響應異步化。並不是所有的用戶請求都提交給服務器。像—些數據驗證和數據處理等都交給Ajax引擎自己來做,,只有確定需要從服務器讀取新數據時再由Ajax引擎代為向服務器提交請求。
來看看和傳統方式的區別

再來看看它們各自的交互
瀏覽器的普通交互方式

瀏覽器的Ajax交互方式

在創建Web站點時,在客戶端執行屏幕更新為用戶提供了很大的靈活性。下面是使用Ajax可以完成的功能:
動態更新購物車的物品總數,無需用戶單擊Update並等待服務器重新發送整個頁面。
提升站點的性能,這是通過減少從服務器下載的數據量而實現的。例如,在Amazon的購物車頁面,當更新籃子中的一項物品的數量時,會重新載入整個頁面,這必須下載32K的數據。如果使用Ajax計算新的總量,服務器只會返回新的總量值,因此所需的帶寬僅為原來的百分之一。
消除了每次用戶輸入時的頁面刷新。例如,在Ajax中,如果用戶在分頁列表上單擊Next,則服務器數據只刷新列表而不是整個頁面。
直接編輯表格數據,而不是要求用戶導航到新的頁面來編輯數據。對於Ajax,當用戶單擊Edit時,可以將靜態表格刷新為內容可編輯的表格。用戶單擊Done之后,就可以發出一個Ajax請求來更新服務器,並刷新表格,使其包含靜態、只讀的數據。

1.4 XMLHttpRequest 對象的三個常用的屬性
1. onreadystatechange 屬性
onreadystatechange 屬性存有處理服務器響應的函數。
下面的代碼定義一個空的函數,可同時對 onreadystatechange 屬性進行設置:
-
xmlHttp.onreadystatechange = function() {
-
//我們需要在這寫一些代碼
-
}
2. readyState 屬性
readyState 屬性存有服務器響應的狀態信息。每當 readyState 改變時,onreadystatechange 函數就會被執行。
readyState 屬性可能的值:
| 狀態 | 描述 |
|---|---|
| 0 | 請求未初始化(在調用 open() 之前) |
| 1 | 請求已提出(調用 send() 之前) |
| 2 | 請求已發送(這里通常可以從響應得到內容頭部) |
| 3 | 請求處理中(響應中通常有部分數據可用,但是服務器還沒有完成響應) |
| 4 | 請求已完成(可以訪問服務器響應並使用它) |
我們要向這個 onreadystatechange 函數添加一條 If 語句,來測試我們的響應是否已完成(意味着可獲得數據):
-
xmlHttp.onreadystatechange = function() {
-
if (xmlHttp.readyState == 4) {
-
//從服務器的response獲得數據
-
}
-
}
3. responseText 屬性
可以通過 responseText 屬性來取回由服務器返回的數據。
在我們的代碼中,我們將把時間文本框的值設置為等於 responseText:
-
xmlHttp.onreadystatechange = function() {
-
if (xmlHttp.readyState == 4) {
-
document.myForm.time.value = xmlHttp.responseText;
-
}
-
}
其它屬性如下:
1.5 xmlhttprequst的方法
1. open() 方法
open() 有三個參數。第一個參數定義發送請求所使用的方法,第二個參數規定服務器端腳本的URL,第三個參數規定應當對請求進行異步地處理。
xmlHttp.open("GET","test.php",true);
2. send() 方法
send() 方法將請求送往服務器。如果我們假設 HTML 文件和 PHP 文件位於相同的目錄,那么代碼是這樣的:
xmlHttp.send(null);
其它方法如下:

二 Ajax編程步驟
為了方便理解,我給AJAX統一了一個流程,要想實現AJAX,就要按照以后步驟走:
- 創建XMLHttpRequest對象。
- 設置請求方式。
- 調用回調函數。
- 發送請求。
下面來看下具體步驟
2.1 創建XMLHttpRequest對象
創建XMLHttp對象的語法是:
var xmlHttp=new XMLHttpRequest();
如果是IE5或者IE6瀏覽器,則使用ActiveX對象,創建方法是:
var xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
一般我們手寫AJAX的時候,首先要判斷該瀏覽器是否支持XMLHttpRequest對象,如果支持則創建該對象,如果不支持則創建ActiveX對象。JS代碼如下:
-
//第一步:創建XMLHttpRequest對象
-
-
var xmlHttp;
-
if (window.XMLHttpRequest) { //非IE
-
xmlHttp = new XMLHttpRequest();
-
} else if (window.ActiveXObject) { //IE
-
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP")
-
}
2.2 設置請求方式
在WEB開發中,請求有兩種形式,一個是get,一個是post,所以在這里需要設置一下具體使用哪個請求,XMLHttpRequest對象的open()方法就是來設置請求方式的。
open()方法
| 功能 | 參數 |
| 規定請求的類型、URL 以及是否異步處理請求 | 參數1:設置請求類型(GET 或 POST),GET與POST的區別請自己百度一下,這里不做解釋; 參數2:文件在服務器上的位置; 參數3:是否異步處理請求,是為true,否為false。 |
如下:
-
//第二步:設置和服務器端交互的相應參數,向路徑http://localhost:8080/JsLearning3/getAjax准備發送數據
-
-
var url = "http://localhost:8080/JsLearning3/getAjax";
-
xmlHttp.open( "POST", url, true);
open方法如下:

GET 還是 POST?
與 POST 相比,GET 更簡單也更快,並且在大部分情況下都能用。然而,在以下情況中,請使用 POST 請求:
無法使用緩存文件(更新服務器上的文件或數據庫)
向服務器發送大量數據(POST 沒有數據量限制)
發送包含未知字符的用戶輸入時,POST 比 GET 更穩定也更可靠
異步 - True 或 False?
AJAX 指的是異步 JavaScript 和 XML(Asynchronous JavaScript and XML)。XMLHttpRequest 對象如果要用於 AJAX 的話,其 open() 方法的 async 參數必須設置為 true:對於 web 開發人員來說,發送異步請求是一個巨大的進步。很多在服務器執行的任務都相當費時。AJAX 出現之前,這可能會引起應用程序掛起或停止。
通過 AJAX,JavaScript 無需等待服務器的響應,而是:
在等待服務器響應時執行其他腳本
當響應就緒后對響應進行處理
2.3 調用回調函數
如果在上一步中open方法的第三個參數選擇的是true,那么當前就是異步請求,這個時候需要寫一個回調函數,XMLHttpRequest對象有一個onreadystatechange屬性,這個屬性返回的是一個匿名的方法,所以回調函數就在這里寫xmlHttp.onreadystatechange=function{},function{}內部就是回調函數的內容。所謂回調函數,就是請求在后台處理完,再返回到前台所實現的功能。在這個例子里,我們的回調函數要實現的功能就是接收后台處理后反饋給前台的數據,然后將這個數據顯示到指定的div上。因為從后台返回的數據可能是錯誤的,所以在回調函數中首先要判斷后台返回的信息是否正確,如果正確才可以繼續執行。代碼如下:
-
//第三步:注冊回調函數
-
-
xmlHttp.onreadystatechange = function() {
-
if (xmlHttp.readyState == 4) {
-
if (xmlHttp.status == 200) {
-
var obj = document.getElementById(id);
-
obj.innerHTML = xmlHttp.responseText;
-
} else {
-
alert( "AJAX服務器返回錯誤!");
-
}
-
}
-
}
在上面代碼中,xmlHttp.readyState是存有XMLHttpRequest 的狀態。從 0 到 4 發生變化。0: 請求未初始化。1: 服務器連接已建立。2: 請求已接收。3: 請求處理中。4: 請求已完成,且響應已就緒。所以這里我們判斷只有當xmlHttp.readyState為4的時候才可以繼續執行。
xmlHttp.status是服務器返回的結果,其中200代表正確。404代表未找到頁面,所以這里我們判斷只有當xmlHttp.status等於200的時候才可以繼續執行。
-
var obj = document.getElementById(id);
-
obj.innerHTML = xmlHttp.responseText;
這段代碼就是回調函數的核心內容,就是獲取后台返回的數據,然后將這個數據賦值給id為testid的div。xmlHttp對象有兩個屬性都可以獲取后台返回的數據,分別是:responseText和responseXML,其中responseText是用來獲得字符串形式的響應數據,responseXML是用來獲得 XML 形式的響應數據。至於選擇哪一個是取決於后台給返回的數據的,這個例子里我們只是顯示一條字符串數據所以選擇的是responseText。responseXML將會在以后的例子中介紹。
AJAX狀態值與狀態碼區別
AJAX狀態值是指,運行AJAX所經歷過的幾種狀態,無論訪問是否成功都將響應的步驟,可以理解成為AJAX運行步驟。如:正在發送,正在響應等,由AJAX對象與服務器交互時所得;使用“ajax.readyState”獲得。(由數字1~4單位數字組成)
AJAX狀態碼是指,無論AJAX訪問是否成功,由HTTP協議根據所提交的信息,服務器所返回的HTTP頭信息代碼,該信息使用“ajax.status”所獲得;(由數字1XX,2XX三位數字組成,詳細查看RFC)
這就是我們在使用AJAX時為什么采用下面的方式判斷所獲得的信息是否正確的原因。
if(ajax.readyState == 4 && ajax.status == 200) {。。。。);}
AJAX運行步驟與狀態值說明
在AJAX實際運行當中,對於訪問XMLHttpRequest(XHR)時並不是一次完成的,而是分別經歷了多種狀態后取得的結果,對於這種狀態在AJAX中共有5種,分別是:
0 - (未初始化)還沒有調用send()方法
1 - (載入)已調用send()方法,正在發送請求
2 - (載入完成)send()方法執行完成,
3 - (交互)正在解析響應內容
4 - (完成)響應內容解析完成,可以在客戶端調用了
對於上面的狀態,其中“0”狀態是在定義后自動具有的狀態值,而對於成功訪問的狀態(得到信息)我們大多數采用“4”進行判斷。
AJAX狀態碼說明
1**:請求收到,繼續處理
2**:操作成功收到,分析、接受
3**:完成此請求必須進一步處理
4**:請求包含一個錯誤語法或不能完成
5**:服務器執行一個完全有效請求失敗
再具體就如下:
100——客戶必須繼續發出請求
101——客戶要求服務器根據請求轉換HTTP協議版本
200——交易成功
201——提示知道新文件的URL
202——接受和處理、但處理未完成
203——返回信息不確定或不完整
204——請求收到,但返回信息為空
205——服務器完成了請求,用戶代理必須復位當前已經瀏覽過的文件
206——服務器已經完成了部分用戶的GET請求
300——請求的資源可在多處得到
301——刪除請求數據
302——在其他地址發現了請求數據
303——建議客戶訪問其他URL或訪問方式
304——客戶端已經執行了GET,但文件未變化
305——請求的資源必須從服務器指定的地址得到
306——前一版本HTTP中使用的代碼,現行版本中不再使用
307——申明請求的資源臨時性刪除
400——錯誤請求,如語法錯誤
401——請求授權失敗
402——保留有效ChargeTo頭響應
403——請求不允許
404——沒有發現文件、查詢或URl
405——用戶在Request-Line字段定義的方法不允許
406——根據用戶發送的Accept拖,請求資源不可訪問
407——類似401,用戶必須首先在代理服務器上得到授權
408——客戶端沒有在用戶指定的餓時間內完成請求
409——對當前資源狀態,請求不能完成
410——服務器上不再有此資源且無進一步的參考地址
411——服務器拒絕用戶定義的Content-Length屬性請求
412——一個或多個請求頭字段在當前請求中錯誤
413——請求的資源大於服務器允許的大小
414——請求的資源URL長於服務器允許的長度
415——請求資源不支持請求項目格式
416——請求中包含Range請求頭字段,在當前請求資源范圍內沒有range指示值,請求也不包含If-Range請求頭字段
417——服務器不滿足請求Expect頭字段指定的期望值,如果是代理服務器,可能是下一級服務器不能滿足請求
500——服務器產生內部錯誤
501——服務器不支持請求的函數
502——服務器暫時不可用,有時是為了防止發生系統過載
503——服務器過載或暫停維修
504——關口過載,服務器使用另一個關口或服務來響應用戶,等待時間設定值較長
505——服務器不支持或拒絕支請求頭中指定的HTTP版本
2.4 發送請求
-
//第四步:設置發送請求的內容和發送報送。然后發送請求
-
-
var params = "userName=" + document.getElementsByName("userName")[0].value + "&userPass=" + document.getElementsByName("userPass")[0].value + "&time=" + Math.random(); // 增加time隨機參數,防止讀取緩存
-
xmlHttp.setRequestHeader( "Content-type", "application/x-www-form-urlencoded;charset=UTF-8"); // 向請求添加 HTTP 頭,POST如果有數據一定加加!!!!
-
xmlHttp.send(params);
如果需要像 HTML 表單那樣 POST 數據,請使用 setRequestHeader() 來添加 HTTP 頭。然后在 send() 方法中規定您希望發送的數據。

