欧美三区四区_av先锋影音资源站_亚洲第一论坛sis_影音先锋2020色资源网_亚洲精品社区_在线免费观看av网站_国产一区二区伦理_亚洲欧美视频一区二区_99视频精品全部免费在线_精精国产xxxx视频在线

使用 JavaScript 和 Ajax 發出異步請求_AJAX教程

編輯Tag賺U幣
教程Tag:暫無Tag,歡迎添加,賺取U幣!

推薦:談Ajax 中的高級請求和響應
對于很多 Web 開發人員來說,只需要生成簡單的請求并接收簡單的響應即可;但是對于希望掌握 Ajax 的開發人員來說,必須要全面理解 HTTP 狀態代碼、就緒狀態和 XMLHttpRequest 對象。在本文中,Brett McLaughlin 將向您介紹各種狀態代碼,并展示瀏覽器如何對

多數 Web 應用程序都使用請求/響應模型從服務器上獲得完整的 HTML 頁面。常常是點擊一個按鈕,等待服務器響應,再點擊另一個按鈕,然后再等待,這樣一個反復的過程。有了 Ajax 和 XMLHttpRequest 對象,就可以使用不必讓用戶等待服務器響應的請求/響應模型了。本文中,Brett McLaughlin 介紹了如何創建能夠適應不同瀏覽器的 XMLHttpRequest 實例,建立和發送請求,并響應服務器。

本系列的上一期文章(請參閱 參考資料 中的鏈接),我們介紹了 Ajax 應用程序,考察了推動 Ajax 應用程序的基本概念。其中的核心是很多您可能已經了解的技術:JavaScript、HTML 和 XHTML、一點動態 HTML 以及 DOM(文檔對象模型)。本文將放大其中的一點,把目光放到具體的 Ajax 細節上。

本文中,您將開始接觸最基本和基礎性的有關 Ajax 的全部對象和編程方法:XMLHttpRequest 對象。該對象實際上僅僅是一個跨越所有 Ajax 應用程序的公共線程,您可能已經預料到,只有徹底理解該對象才能充分發揮編程的潛力。事實上,有時您會發現,要正確地使用 XMLHttpRequest,顯然不能 使用 XMLHttpRequest。這到底是怎么回事呢?

Web 2.0 一瞥

在深入研究代碼之前首先看看最近的觀點 —— 一定要十分清楚 Web 2.0 這個概念。聽到 Web 2.0 這個詞的時候,應該首先問一問 “Web 1.0 是什么?” 雖然很少聽人提到 Web 1.0,實際上它指的就是具有完全不同的請求和響應模型的傳統 Web。比如,到 Amazon.com 網站上點擊一個按鈕或者輸入搜索項。就會對服務器發送一個請求,然后響應再返回到瀏覽器。該請求不僅僅是圖書和書目列表,而是另一個完整的 HTML 頁面。因此當 Web 瀏覽器用新的 HTML 頁面重繪時,可能會看到閃爍或抖動。事實上,通過看到的每個新頁面可以清晰地看到請求和響應。

Web 2.0(在很大程度上)消除了這種看得見的往復交互。比如訪問 Google Maps 或 Flickr 這樣的站點(到這些支持 Web 2.0 和 Ajax 站點的鏈接請參閱 參考資料)。比如在 Google Maps 上,您可以拖動地圖,放大和縮小,只有很少的重繪操作。當然這里仍然有請求和響應,只不過都藏到了幕后。作為用戶,體驗更加舒適,感覺很像桌面應用程序。這種新的感受和范型就是當有人提到 Web 2.0 時您所體會到的。

需要關心的是如何使這些新的交互成為可能。顯然,仍然需要發出請求和接收響應,但正是針對每次請求/響應交互的 HTML 重繪造成了緩慢、笨拙的 Web 交互的感受。因此很清楚,我們需要一種方法使發送的請求和接收的響應只 包含需要的數據而不是整個 HTML 頁面。惟一需要獲得整個新 HTML 頁面的時候就是希望用戶看到 新頁面的時候。

但多數交互都是在已有頁面上增加細節、修改主體文本或者覆蓋原有數據。這些情況下,Ajax 和 Web 2.0 方法允許在不 更新整個 HTML 頁面的情況下發送和接收數據。對于那些經常上網的人,這種能力可以讓您的應用程序感覺更快、響應更及時,讓他們不時地光顧您的網站。

XMLHttpRequest 簡介

要真正實現這種絢麗的奇跡,必須非常熟悉一個 JavaScript 對象,即 XMLHttpRequest。這個小小的對象實際上已經在幾種瀏覽器中存在一段時間了,它是本專欄今后幾個月中要介紹的 Web 2.0、Ajax 和大部分其他內容的核心。為了讓您快速地大體了解它,下面給出將要用于該對象的很少的幾個 方法和屬性。

·open():建立到服務器的新請求。
·send():向服務器發送請求。
·abort():退出當前請求。
·readyState:提供當前 HTML 的就緒狀態。
·responseText:服務器返回的請求響應文本。

如果不了解這些(或者其中的任何 一個),您也不用擔心,后面幾篇文章中我們將介紹每個方法和屬性。現在應該 了解的是,明確用 XMLHttpRequest 做什么。要注意這些方法和屬性都與發送請求及處理響應有關。事實上,如果看到 XMLHttpRequest 的所有方法和屬性,就會發現它們都 與非常簡單的請求/響應模型有關。顯然,我們不會遇到特別新的 GUI 對象或者創建用戶交互的某種超極神秘的方法,我們將使用非常簡單的請求和非常簡單的響應。聽起來似乎沒有多少吸引力,但是用好該對象可以徹底改變您的應用程序。

簡單的 new

首先需要創建一個新變量并賦給它一個 XMLHttpRequest 對象實例。這在 JavaScript 中很簡單,只要對該對象名使用 new 關鍵字即可,如 清單 1 所示。

清單 1. 創建新的 XMLHttpRequest 對象

<script language="javascript" type="text/javascript">
var request = new XMLHttpRequest();
</script>

不難吧?記住,JavaScript 不要求指定變量類型,因此不需要像 清單 2 那樣做(在 Java 語言中可能需要這樣)。

清單 2. 創建 XMLHttpRequest 的 Java 偽代碼

XMLHttpRequest request = new XMLHttpRequest();

因此在 JavaScript 中用 var 創建一個變量,給它一個名字(如 “request”),然后賦給它一個新的 XMLHttpRequest 實例。此后就可以在函數中使用該對象了。

錯誤處理

在實際上各種事情都可能出錯,而上面的代碼沒有提供任何錯誤處理。較好的辦法是創建該對象,并在出現問題時優雅地退出。比如,任何較早的瀏覽器(不論您是否相信,仍然有人在使用老版本的 Netscape Navigator)都不支持 XMLHttpRequest,您需要讓這些用戶知道有些地方出了問題。清單 3 說明如何創建該對象,以便在出現問題的時候發出 JavaScript 警告。

清單 3. 創建具有錯誤處理能力的 XMLHttpRequest

 

<script language="javascript" type="text/javascript">
var request = false;
try {
request = new XMLHttpRequest();
} catch (failed) {
request = false;
}

if (!request)
alert("Error initializing XMLHttpRequest!");
</script>

一定要理解這些步驟:

1、創建一個新變量 request 并賦值 false。后面將使用 false 作為判定條件,它表示還沒有創建 XMLHttpRequest 對象。
2、增加 try/catch 塊:
1)嘗試創建 XMLHttpRequest 對象。
2)如果失敗(catch (failed))則保證 request 的值仍然為 false。
3、檢查 request 是否仍為 false(如果一切正常就不會是 false)。
4、如果出現問題(request 是 false)則使用 JavaScript 警告通知用戶出現了問題。

代碼非常簡單,對大多數 JavaScript 和 Web 開發人員來說,真正理解它要比讀寫代碼花更長的時間。現在已經得到了一段帶有錯誤檢查的 XMLHttpRequest 對象創建代碼,還可以告訴您哪兒出了問題。

應付 Microsoft

看起來似乎一切良好,至少在用 Internet Explorer 試驗這些代碼之前是這樣的。如果這樣試驗的話,就會看到 圖 1 所示的糟糕情形。

圖 1. Internet Explorer 報告錯誤

顯然有什么地方不對勁,而 Internet Explorer 很難說是一種過時的瀏覽器,因為全世界有 70% 在使用 Internet Explorer。換句話說,如果不支持 Microsoft 和 Internet Explorer 就不會受到 Web 世界的歡迎!因此我們需要采用不同的方法處理 Microsoft 瀏覽器。

經驗證發現 Microsoft 支持 Ajax,但是其 XMLHttpRequest 版本有不同的稱呼。事實上,它將其稱為幾種 不同的東西。如果使用較新版本的 Internet Explorer,則需要使用對象 Msxml2.XMLHTTP,而較老版本的 Internet Explorer 則使用 Microsoft.XMLHTTP。我們需要支持這兩種對象類型(同時還要支持非 Microsoft 瀏覽器)。請看看 清單 4,它在前述代碼的基礎上增加了對 Microsoft 的支持。

Microsoft 參與了嗎?

關于 Ajax 和 Microsoft 對該領域不斷增長的興趣和參與已經有很多文章進行了介紹。事實上,據說 Microsoft 最新版本的 Internet Explorer —— version 7.0,將在 2006 年下半年推出 —— 將開始直接支持 XMLHttpRequest,讓您使用 new 關鍵字代替所有的 Msxml2.XMLHTTP 創建代碼。但不要太激動,仍然需要支持舊的瀏覽器,因此跨瀏覽器代碼不會很快消失。

清單 4. 增加對 Microsoft 瀏覽器的支持

 

<script language="javascript" type="text/javascript">
var request = false;
try {
request = new XMLHttpRequest();
} catch (trymicrosoft) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = false;
}
}
}

if (!request)
alert("Error initializing XMLHttpRequest!");
</script>

 

很容易被這些花括號迷住了眼睛,因此下面分別介紹每一步:

1、創建一個新變量 request 并賦值 false。使用 false 作為判斷條件,它表示還沒有創建 XMLHttpRequest 對象。
2、增加 try/catch 塊:
1)嘗試創建 XMLHttpRequest 對象。
2)如果失敗(catch (trymicrosoft)):
1>嘗試使用較新版本的 Microsoft 瀏覽器創建 Microsoft 兼容的對象(Msxml2.XMLHTTP)。
2> 如果失敗(catch (othermicrosoft))嘗試使用較老版本的 Microsoft 瀏覽器創建 Microsoft 兼容的對象(Microsoft.XMLHTTP)。
2)如果失敗(catch (failed))則保證 request 的值仍然為 false。
3、檢查 request 是否仍然為 false(如果一切順利就不會是 false)。
4、如果出現問題(request 是 false)則使用 JavaScript 警告通知用戶出現了問題。

這樣修改代碼之后再使用 Internet Explorer 試驗,就應該看到已經創建的表單(沒有錯誤消息)。我實驗的結果如 圖 2 所示。

圖 2. Internet Explorer 正常工作

靜態與動態

再看一看清單 1、3 和 4,注意,所有這些代碼都直接嵌套在 script 標記中。像這種不放到方法或函數體中的 JavaScript 代碼稱為靜態 JavaScript。就是說代碼是在頁面顯示給用戶之前的某個時候運行。(雖然根據規范不能完全精確地 知道這些代碼何時運行對瀏覽器有什么影響,但是可以保證這些代碼在用戶能夠與頁面交互之前運行。)這也是多數 Ajax 程序員創建 XMLHttpRequest 對象的一般方式。

就是說,也可以像 清單 5 那樣將這些代碼放在一個方法中。

清單 5. 將 XMLHttpRequest 創建代碼移動到方法中

 

<script language="javascript" type="text/javascript">

var request;

function createRequest() {
try {
request = new XMLHttpRequest();
} catch (trymicrosoft) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = false;
}
}
}

if (!request)
alert("Error initializing XMLHttpRequest!");
}
</script>

 

如果按照這種方式編寫代碼,那么在處理 Ajax 之前需要調用該方法。因此還需要 清單 6 這樣的代碼。

清單 6. 使用 XMLHttpRequest 的創建方法

 

<script language="javascript" type="text/javascript">

var request;

function createRequest() {
try {
request = new XMLHttpRequest();
} catch (trymicrosoft) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = false;
}
}
}

if (!request)
alert("Error initializing XMLHttpRequest!");
}

function getCustomerInfo() {
createRequest();
// Do something with the request variable
}
</script>

 

此代碼惟一的問題是推遲了錯誤通知,這也是多數 Ajax 程序員不采用這一方法的原因。假設一個復雜的表單有 10 或 15 個字段、選擇框等,當用戶在第 14 個字段(按照表單順序從上到下)輸入文本時要激活某些 Ajax 代碼。這時候運行 getCustomerInfo() 嘗試創建一個 XMLHttpRequest 對象,但(對于本例來說)失敗了。然后向用戶顯示一條警告,明確地告訴他們不能使用該應用程序。但用戶已經花費了很多時間在表單中輸入數據!這是非常令人討厭的,而討厭顯然不會吸引用戶再次訪問您的網站。

如果使用靜態 JavaScript,用戶在點擊頁面的時候很快就會看到錯誤信息。這樣也很煩人,是不是?可能令用戶錯誤地認為您的 Web 應用程序不能在他的瀏覽器上運行。不過,當然要比他們花費了 10 分鐘輸入信息之后再顯示同樣的錯誤要好。因此,我建議編寫靜態的代碼,讓用戶盡可能早地發現問題。

用 XMLHttpRequest 發送請求

得到請求對象之后就可以進入請求/響應循環了。記住,XMLHttpRequest 惟一的目的是讓您發送請求和接收響應。其他一切都是 JavaScript、CSS 或頁面中其他代碼的工作:改變用戶界面、切換圖像、解釋服務器返回的數據。準備好 XMLHttpRequest 之后,就可以向服務器發送請求了。

歡迎使用沙箱

Ajax 采用一種沙箱安全模型。因此,Ajax 代碼(具體來說就是 XMLHttpRequest 對象)只能對所在的同一個域發送請求。以后的文章中將進一步介紹安全和 Ajax,現在只要知道在本地機器上運行的代碼只能對本地機器上的服務器端腳本發送請求。如果讓 Ajax 代碼在 www.breakneckpizza.com 上運行,則必須 www.breakneck.com 中運行的腳本發送請求。

設置服務器 URL

首先要確定連接的服務器的 URL。這并不是 Ajax 的特殊要求,但仍然是建立連接所必需的,顯然現在您應該知道如何構造 URL 了。多數應用程序中都會結合一些靜態數據和用戶處理的表單中的數據來構造該 URL。比如,清單 7 中的 JavaScript 代碼獲取電話號碼字段的值并用其構造 URL。

清單 7. 建立請求 URL

 

<script language="javascript" type="text/javascript">
var request = false;
try {
request = new XMLHttpRequest();
} catch (trymicrosoft) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = false;
}
}
}

if (!request)
alert("Error initializing XMLHttpRequest!");

function getCustomerInfo() {
var phone = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
}
</script>

這里沒有難懂的地方。首先,代碼創建了一個新變量 phone,并把 ID 為 “phone” 的表單字段的值賦給它。清單 8 展示了這個表單的 XHTML,其中可以看到 phone 字段及其 id 屬性。

清單 8. Break Neck Pizza 表單

<body>
<p><img src="breakneck-logo_4c.gif" alt="Break Neck Pizza" /></p>
<form action="POST">
<p>Enter your phone number:
<input type="text" size="14" name="phone" id="phone"
onChange="getCustomerInfo();" />
</p>
<p>Your order will be delivered t</p>
<div id="address"></div>
<p>Type your order in here:</p>
<p><textarea name="order" rows="6" cols="50" id="order"></textarea></p>
<p><input type="submit" value="Order Pizza" id="submit" /></p>
</form>
</body>

還要注意,當用戶輸入電話號碼或者改變電話號碼時,將觸發 清單 8 所示的 getCustomerInfo() 方法。該方法取得電話號碼并構造存儲在 url 變量中的 URL 字符串。記住,由于 Ajax 代碼是沙箱型的,因而只能連接到同一個域,實際上 URL 中不需要域名。該例中的腳本名為 /cgi-local/lookupCustomer.php。最后,電話號碼作為 GET 參數附加到該腳本中:"phone=" + escape(phone)。

如果以前沒用見過 escape() 方法,它用于轉義不能用明文正確發送的任何字符。比如,電話號碼中的空格將被轉換成字符 %20,從而能夠在 URL 中傳遞這些字符。

可以根據需要添加任意多個參數。比如,如果需要增加另一個參數,只需要將其附加到 URL 中并用 “與”(&)字符分開 [第一個參數用問號(?)和腳本名分開]。

打開請求

有了要連接的 URL 后就可以配置請求了。可以用 XMLHttpRequest 對象的 open() 方法來完成。該方法有五個參數:

request-type:發送請求的類型。典型的值是 GET 或 POST,但也可以發送 HEAD 請求。
url:要連接的 URL。
asynch:如果希望使用異步連接則為 true,否則為 false。該參數是可選的,默認為 true。
username:如果需要身份驗證,則可以在此指定用戶名。該可選參數沒有默認值。 password:如果需要身份驗證,則可以在此指定口令。該可選參數沒有默認值。

open() 是打開嗎?
Internet 開發人員對 open() 方法到底做什么沒有達成一致。但它實際上并不是 打開一個請求。如果監控 XHTML/Ajax 頁面及其連接腳本之間的網絡和數據傳遞,當調用 open() 方法時將看不到任何通信。不清楚為何選用了這個名字,但顯然不是一個好的選擇。

通常使用其中的前三個參數。事實上,即使需要異步連接,也應該指定第三個參數為 “true”。這是默認值,但堅持明確指定請求是異步的還是同步的更容易理解。

將這些結合起來,通常會得到 清單 9 所示的一行代碼。

清單 9. 打開請求

function getCustomerInfo() {
var phone = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
request.open("GET", url, true);
}

一旦設置好了 URL,其他就簡單了。多數請求使用 GET 就夠了(后面的文章中將看到需要使用 POST 的情況),再加上 URL,這就是使用 open() 方法需要的全部內容了。

挑戰異步性

本系列的后面一篇文章中,我將用很多時間編寫和使用異步代碼,但是您應該明白為什么 open() 的最后一個參數這么重要。在一般的請求/響應模型中,比如 Web 1.0,客戶機(瀏覽器或者本地機器上運行的代碼)向服務器發出請求。該請求是同步的,換句話說,客戶機等待服務器的響應。當客戶機等待的時候,至少會用某種形式通知您在等待:

·沙漏(特別是 Windows 上)。
·旋轉的皮球(通常在 Mac 機器上)。
·應用程序基本上凍結了,然后過一段時間光標變化了。

這正是 Web 應用程序讓人感到笨拙或緩慢的原因 —— 缺乏真正的交互性。按下按鈕時,應用程序實際上變得不能使用,直到剛剛觸發的請求得到響應。如果請求需要大量服務器處理,那么等待的時間可能很長(至少在這個多處理器、DSL 沒有等待的世界中是如此)。

而異步請求不 等待服務器響應。發送請求后應用程序繼續運行。用戶仍然可以在 Web 表單中輸入數據,甚至離開表單。沒有旋轉的皮球或者沙漏,應用程序也沒有明顯的凍結。服務器悄悄地響應請求,完成后告訴原來的請求者工作已經結束(具體的辦法很快就會看到)。結果是,應用程序感覺不 那么遲鈍或者緩慢,而是響應迅速、交互性強,感覺快多了。這僅僅是 Web 2.0 的一部分,但它是很重要的一部分。所有老套的 GUI 組件和 Web 設計范型都不能克服緩慢、同步的請求/響應模型。

發送請求

一旦用 open() 配置好之后,就可以發送請求了。幸運的是,發送請求的方法的名稱要比 open() 適當,它就是 send()。

send() 只有一個參數,就是要發送的內容。但是在考慮這個方法之前,回想一下前面已經通過 URL 本身發送過數據了:

var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);

雖然可以使用 send() 發送數據,但也能通過 URL 本身發送數據。事實上,GET 請求(在典型的 Ajax 應用中大約占 80%)中,用 URL 發送數據要容易得多。如果需要發送安全信息或 XML,可能要考慮使用 send() 發送內容(本系列的后續文章中將討論安全數據和 XML 消息)。如果不需要通過 send() 傳遞數據,則只要傳遞 null 作為該方法的參數即可。因此您會發現在本文中的例子中只需要這樣發送請求(參見 清單 10)。

清單 10. 發送請求

function getCustomerInfo() {
var phone = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
request.open("GET", url, true);
request.send(null);
}

指定回調方法

現在我們所做的只有很少一點是新的、革命性的或異步的。必須承認,open() 方法中 “true” 這個小小的關鍵字建立了異步請求。但是除此之外,這些代碼與用 Java servlet 及 JSP、PHP 或 Perl 編程沒有什么兩樣。那么 Ajax 和 Web 2.0 最大的秘密是什么呢?秘密就在于 XMLHttpRequest 的一個簡單屬性 onreadystatechange。

首先一定要理解這些代碼中的流程(如果需要請回顧 清單 10)。建立其請求然后發出請求。此外,因為是異步請求,所以 JavaScript 方法(例子中的 getCustomerInfo())不會等待服務器。因此代碼將繼續執行,就是說,將退出該方法而把控制返回給表單。用戶可以繼續輸入信息,應用程序不會等待服務器。

這就提出了一個有趣的問題:服務器完成了請求之后會發生什么?答案是什么也不發生,至少對現在的代碼而言如此!顯然這樣不行,因此服務器在完成通過 XMLHttpRequest 發送給它的請求處理之后需要某種指示說明怎么做。

在 JavaScript 中引用函數:
JavaScript 是一種弱類型的語言,可以用變量引用任何東西。因此如果聲明了一個函數 updatePage(),JavaScript 也將該函數名看作是一個變量。換句話說,可用變量名 updatePage 在代碼中引用函數。

清單 11. 設置回調方法

function getCustomerInfo() {
var phone = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
request.open("GET", url, true);
request.onreadystatechange = updatePage;
request.send(null);
}

需要特別注意的是該屬性在代碼中設置的位置 —— 它是在調用 send() 之前 設置的。發送請求之前必須設置該屬性,這樣服務器在回答完成請求之后才能查看該屬性。現在剩下的就只有編寫 updatePage() 方法了,這是本文最后一節要討論的重點。

處理服務器響應

發送請求,用戶高興地使用 Web 表單(同時服務器在處理請求),而現在服務器完成了請求處理。服務器查看 onreadystatechange 屬性確定要調用的方法。除此以外,可以將您的應用程序看作其他應用程序一樣,無論是否異步。換句話說,不一定要采取特殊的動作編寫響應服務器的方法,只需要改變表單,讓用戶訪問另一個 URL 或者做響應服務器需要的任何事情。這一節我們重點討論對服務器的響應和一種典型的動作 —— 即時改變用戶看到的表單中的一部分。

回調和 Ajax

現在我們已經看到如何告訴服務器完成后應該做什么:將 XMLHttpRequest 對象的 onreadystatechange 屬性設置為要運行的函數名。這樣,當服務器處理完請求后就會自動調用該函數。也不需要擔心該函數的任何參數。我們從一個簡單的方法開始,如 清單 12 所示。

清單 12. 回調方法的代碼

 

<script language="javascript" type="text/javascript">
var request = false;
try {
request = new XMLHttpRequest();
} catch (trymicrosoft) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = false;
}
}
}

if (!request)
alert("Error initializing XMLHttpRequest!");

function getCustomerInfo() {
var phone = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
request.open("GET", url, true);
request.onreadystatechange = updatePage;
request.send(null);
}

function updatePage() {
alert("Server is done!");
}
</script>

它僅僅發出一些簡單的警告,告訴您服務器什么時候完成了任務。在自己的網頁中試驗這些代碼,然后在瀏覽器中打開(如果希望查看該例中的 XHTML,請參閱 清單 8)。輸入電話號碼然后離開該字段,將看到一個彈出的警告窗口(如 圖 3 所示),但是點擊 OK 又出現了……

圖 3. 彈出警告的 Ajax 代碼

根據瀏覽器的不同,在表單停止彈出警告之前會看到兩次、三次甚至四次警告。這是怎么回事呢?原來我們還沒有考慮 HTTP 就緒狀態,這是請求/響應循環中的一個重要部分。

HTTP 就緒狀態

前面提到,服務器在完成請求之后會在 XMLHttpRequest 的 onreadystatechange 屬性中查找要調用的方法。這是真的,但還不完整。事實上,每當 HTTP 就緒狀態改變時它都會調用該方法。這意味著什么呢?首先必須理解 HTTP 就緒狀態。

HTTP 就緒狀態表示請求的狀態或情形。它用于確定該請求是否已經開始、是否得到了響應或者請求/響應模型是否已經完成。它還可以幫助確定讀取服務器提供的響應文本或數據是否安全。在 Ajax 應用程序中需要了解五種就緒狀態:

·0:請求沒有發出(在調用 open() 之前)。
·1:請求已經建立但還沒有發出(調用 send() 之前)。
·2:請求已經發出正在處理之中(這里通常可以從響應得到內容頭部)。
·3:請求已經處理,響應中通常有部分數據可用,但是服務器還沒有完成響應。
·4:響應已完成,可以訪問服務器響應并使用它。

與大多數跨瀏覽器問題一樣,這些就緒狀態的使用也不盡一致。您也許期望任務就緒狀態從 0 到 1、2、3 再到 4,但實際上很少是這種情況。一些瀏覽器從不報告 0 或 1 而直接從 2 開始,然后是 3 和 4。其他瀏覽器則報告所有的狀態。還有一些則多次報告就緒狀態 1。在上一節中看到,服務器多次調用 updatePage(),每次調用都會彈出警告框 —— 可能和預期的不同!

對于 Ajax 編程,需要直接處理的惟一狀態就是就緒狀態 4,它表示服務器響應已經完成,可以安全地使用響應數據了。基于此,回調方法中的第一行應該如 清單 13 所示。

清單 13. 檢查就緒狀態

function updatePage() {
if (request.readyState == 4)
alert("Server is done!");
}

修改后就可以保證服務器的處理已經完成。嘗試運行新版本的 Ajax 代碼,現在就會看到與預期的一樣,只顯示一次警告信息了。

HTTP 狀態碼

雖然 清單 13 中的代碼看起來似乎不錯,但是還有一個問題 —— 如果服務器響應請求并完成了處理但是報告了一個錯誤怎么辦?要知道,服務器端代碼應該明白它是由 Ajax、JSP、普通 HTML 表單或其他類型的代碼調用的,但只能使用傳統的 Web 專用方法報告信息。而在 Web 世界中,HTTP 代碼可以處理請求中可能發生的各種問題。

比方說,您肯定遇到過輸入了錯誤的 URL 請求而得到 404 錯誤碼的情形,它表示該頁面不存在。這僅僅是 HTTP 請求能夠收到的眾多錯誤碼中的一種(完整的狀態碼列表請參閱 參考資料 中的鏈接)。表示所訪問數據受到保護或者禁止訪問的 403 和 401 也很常見。無論哪種情況,這些錯誤碼都是從完成的響應 得到的。換句話說,服務器履行了請求(即 HTTP 就緒狀態是 4)但是沒有返回客戶機預期的數據。

因此除了就緒狀態外,還需要檢查 HTTP 狀態。我們期望的狀態碼是 200,它表示一切順利。如果就緒狀態是 4 而且狀態碼是 200,就可以處理服務器的數據了,而且這些數據應該就是要求的數據(而不是錯誤或者其他有問題的信息)。因此還要在回調方法中增加狀態檢查,如 清單 14 所示。

清單 14. 檢查 HTTP 狀態碼

function updatePage() {
if (request.readyState == 4)
if (request.status == 200)
alert("Server is done!");
}

為了增加更健壯的錯誤處理并盡量避免過于復雜,可以增加一兩個狀態碼檢查,請看一看 清單 15 中修改后的 updatePage() 版本。

清單 15. 增加一點錯誤檢查

function updatePage() {
if (request.readyState == 4)
if (request.status == 200)
alert("Server is done!");
else if (request.status == 404)
alert("Request URL does not exist");
else
alert("Error: status code is " + request.status);
}

現在將 getCustomerInfo() 中的 URL 改為不存在的 URL 看看會發生什么。應該會看到警告信息說明要求的 URL 不存在 —— 好極了!很難處理所有的錯誤條件,但是這一小小的改變能夠涵蓋典型 Web 應用程序中 80% 的問題。

讀取響應文本

現在可以確保請求已經處理完成(通過就緒狀態),服務器給出了正常的響應(通過狀態碼),最后我們可以處理服務器返回的數據了。返回的數據保存在 XMLHttpRequest 對象的 responseText 屬性中。

關于 responseText 中的文本內容,比如格式和長度,有意保持含糊。這樣服務器就可以將文本設置成任何內容。比方說,一種腳本可能返回逗號分隔的值,另一種則使用管道符(即 | 字符)分隔的值,還有一種則返回長文本字符串。何去何從由服務器決定。

在本文使用的例子中,服務器返回客戶的上一個訂單和客戶地址,中間用管道符分開。然后使用訂單和地址設置表單中的元素值,清單 16 給出了更新顯示內容的代碼。

清單 16. 處理服務器響應

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

首先,得到 responseText 并使用 JavaScript split() 方法從管道符分開。得到的數組放到 response 中。數組中的第一個值 —— 上一個訂單 —— 用 response[0] 訪問,被設置為 ID 為 “order” 的字段的值。第二個值 response[1],即客戶地址,則需要更多一點處理。因為地址中的行用一般的行分隔符(“\n”字符)分隔,代碼中需要用 XHTML 風格的行分隔符 <br /> 來代替。替換過程使用 replace() 函數和正則表達式完成。最后,修改后的文本作為 HTML 表單 div 中的內部 HTML。結果就是表單突然用客戶信息更新了,如圖 4 所示。

圖 4. 收到客戶數據后的 Break Neck 表單

結束本文之前,我還要介紹 XMLHttpRequest 的另一個重要屬性 responseXML。如果服務器選擇使用 XML 響應則該屬性包含(也許您已經猜到)XML 響應。處理 XML 響應和處理普通文本有很大不同,涉及到解析、文檔對象模型(DOM)和其他一些問題。后面的文章中將進一步介紹 XML。但是因為 responseXML 通常和 responseText 一起討論,這里有必要提一提。對于很多簡單的 Ajax 應用程序 responseText 就夠了,但是您很快就會看到通過 Ajax 應用程序也能很好地處理 XML。

結束語

您可能對 XMLHttpRequest 感到有點厭倦了,我很少看到一整篇文章討論一個對象,特別是這種簡單的對象。但是您將在使用 Ajax 編寫的每個頁面和應用程序中反復使用該對象。坦白地說,關于 XMLHttpRequest 還真有一些可說的內容。下一期文章中將介紹如何在請求中使用 POST 及 GET,來設置請求中的內容頭部和從服務器響應讀取內容頭部,理解如何在請求/響應模型中編碼請求和處理 XML。

再往后我們將介紹常見 Ajax 工具箱。這些工具箱實際上隱藏了本文所述的很多細節,使得 Ajax 編程更容易。您也許會想,既然有這么多工具箱為何還要對底層的細節編碼。答案是,如果不知道應用程序在做什么,就很難發現應用程序中的問題。

因此不要忽略這些細節或者簡單地瀏覽一下,如果便捷華麗的工具箱出現了錯誤,您就不必撓頭或者發送郵件請求支持了。如果了解如何直接使用 XMLHttpRequest,就會發現很容易調試和解決最奇怪的問題。只有讓其解決您的問題,工具箱才是好東西。

因此請熟悉 XMLHttpRequest 吧。事實上,如果您有使用工具箱的 Ajax 代碼,可以嘗試使用 XMLHttpRequest 對象及其屬性和方法重新改寫。這是一種不錯的練習,可以幫助您更好地理解其中的原理。

分享:XMLHTTP組件相關技術資料
一、數據庫遠程管理技術 基于互聯網的廣域網現代應用中的一個重要環節是數據庫遠程監控。首先簡單回顧一下互聯網上的數據庫遠程管理技術的發展過程和方式: 早期通過編寫CGI-BIN程序模塊進行數據庫遠程管理。但CGI-BIN的運行速度慢,維護很不方便,現在已經

來源:模板無憂//所屬分類:AJAX教程/更新時間:2010-04-24
相關AJAX教程
天天做天天摸天天爽国产一区| 国产九一精品| 国产成人精品免费在线| 精品国产自在久精品国产| 成人区精品一区二区| 国产51自产区| 在线观看xxx| 麻豆极品一区二区三区| 日韩午夜小视频| 免费国产一区二区| 极品色av影院| 久久成人福利| 国产精品欧美一区喷水| 欧美国产日韩一区二区| 欧美激情国产精品日韩| 91国内精品视频| 亚洲三级免费| 欧美日韩不卡在线| 亚洲精品免费网站| 久久久久久久久久久久| 亚洲精品一二三**| 亚洲国产精品成人综合| 欧美大胆在线视频| 免费激情视频在线观看| 亚洲免费视频网| 免费在线看成人av| 亚洲国产又黄又爽女人高潮的| 色就是色欧美| 日韩毛片在线视频| 羞羞色午夜精品一区二区三区| 狠狠色香婷婷久久亚洲精品| 亚洲综合色av| 日本高清黄色片| 欧美巨大xxxx| 一区二区三区四区中文字幕| 国产激情久久久久| 污污污www精品国产网站| 中文字幕综合| 久久久精品一品道一区| 国外成人在线直播| 日韩大尺度视频| а天堂中文最新一区二区三区| 国产精品国产三级国产传播| 97人妻人人澡人人爽人人精品| 亚洲人成毛片在线播放女女| 欧美妇女性影城| 久久久综合亚洲91久久98| 91视频综合网| 99视频精品视频高清免费| 日韩欧美在线字幕| 精品一卡二卡三卡四卡日本乱码 | 久久国产精品久久国产精品| 国产又大又黄又粗的视频| 免费观看的毛片| 成人黄页在线观看| 欧美激情国产日韩精品一区18| 国产女同无遮挡互慰高潮91| 黄色成人在线观看网站| 欧美国产综合一区二区| 欧洲午夜精品久久久| 你懂的在线观看网站| 噜噜噜狠狠夜夜躁精品仙踪林| 一区二区高清视频在线观看| 91福利视频导航| 久久久久久久蜜桃| 伊人天天综合| 亚洲国产精品va在线| 欧美精品久久久久久久自慰| 亚洲乱熟女一区二区| 成人久久视频在线观看| 国内精品久久久久久久| 视频免费在线观看| 亚洲综合图色| 欧洲人成人精品| 亚洲免费在线精品一区| 亚洲天堂777| 国产精品一二三区在线| 久久6精品影院| 亚洲精品久久一区二区三区777| 欧美影院视频| 亚洲成人免费在线观看| 久久影院理伦片| 亚洲欧美日韩一区二区三区四区| 免费日本视频一区| 久久精品国产亚洲7777| 自拍一级黄色片| 成人三级毛片| 色老头久久综合| 在线观看成人av电影| 99这里有精品视频| 97久久超碰国产精品| 日本精品在线视频| 女人裸体性做爰全过| 亚洲精品一区二区妖精| 精品国产欧美一区二区| 国产免费毛卡片| 成人精品高清在线视频| 亚洲欧美乱综合| 国产伦精品一区二区三区视频免费| 国产成人无码精品久在线观看| 丝袜美腿亚洲一区| 精品激情国产视频| 中文字幕一区二区人妻电影丶| 久久不见久久见免费视频7| 欧美日韩日本视频| 91大学生片黄在线观看| 天天操天天干天天干| 国产视频一区不卡| 99热国产免费| 成人a v视频| 激情六月婷婷久久| 91精品国产色综合| 天美传媒免费在线观看| 亚洲少妇在线| 日韩在线观看免费全| av不卡中文字幕| 国产欧美日韩影院| 日韩欧美黄色影院| 激情内射人妻1区2区3区| 日韩视频在线直播| 在线日韩国产精品| 青草视频在线观看视频| 狂野欧美性猛交xxxx| 亚洲电影一区二区| 中文字幕日韩精品久久| 成人亚洲欧美| 亚洲一区二区三区四区在线| 亚洲精美视频| 亚洲女同av| 亚洲尤物视频在线| 先锋影音亚洲资源| 无码精品在线观看| 亚洲主播在线观看| 伊人久久大香线蕉综合75| 欧美一区久久久| 亚洲国产欧美日韩另类综合 | 日日骚av一区| 偷拍女澡堂一区二区三区| 欧美成人亚洲| 日韩一区视频在线| 变态另类ts人妖一区二区| 亚洲国产高清一区| 久久视频精品在线| av黄色在线免费观看| 中文高清一区| 久久99精品久久久久久噜噜| 一级特黄曰皮片视频| 亚洲在线日韩| 欧美亚洲成人网| xxxx 国产| 国产99久久久国产精品| 亚洲精品免费av| 国产伦精品一区二区三区视频痴汉 | 手机在线成人av| 亚洲激情影院| 欧美激情精品在线| 免费在线视频一区二区| 国产麻豆9l精品三级站| 91牛牛免费视频| 夜夜嗨aⅴ一区二区三区| 国产欧美精品国产国产专区| 免费国产在线精品一区二区三区| 香港一级纯黄大片| 午夜欧美在线一二页| 少妇人妻无码专区视频| 欧美日韩麻豆| 日韩av在线直播| 一本色道综合久久欧美日韩精品| 国产欧美精品| 88xx成人精品| 国产精品免费精品一区| 久久久亚洲欧洲日产国码αv| 久久99精品久久久久子伦| 天天插天天干天天操| 欧美性猛交xxxxx免费看| 精品这里只有精品| 久草成人在线| 亚洲网站在线播放| 国产午夜福利一区| 国产乱码精品一区二区三区av| 成人天堂噜噜噜| 亚洲第一天堂影院| 婷婷开心久久网| 天天综合网日韩| 亚洲激情中文在线| 国内精品国产三级国产在线专| 99热只有这里有精品| 亚洲国产精品精华液2区45| 在线观看亚洲视频啊啊啊啊| 麻豆一区在线| 亚洲第一偷拍网| 国产日韩视频一区| 丝袜美腿亚洲色图| 91av一区二区三区| 亚洲欧美日韩综合在线| 欧美视频你懂的| 风韵丰满熟妇啪啪区老熟熟女| 国产九九精品| 国产欧美日韩免费看aⅴ视频| 精品女同一区二区三区| 欧美视频国产精品| www.久久av.com| 国产日韩欧美一区二区三区在线观看| 国产成人精品网站| 国内老熟妇对白xxxxhd| 日韩欧美亚洲成人| 日本黄色的视频| 国产农村妇女精品一区二区| 国产精品色婷婷视频| 三级小视频在线观看| 欧美人狂配大交3d怪物一区 | 日韩视频在线直播| 亚洲欧美国产视频| 欧美做爰爽爽爽爽爽爽| 久久综合国产精品| 奇米777四色影视在线看| 国产亚洲一区| 久久久免费高清电视剧观看| 这里只有精品免费视频| 亚洲成人动漫av| 久久久久xxxx| 日韩二区在线观看| 国产欧美日韩视频一区二区三区| 日韩久久一区| 亚洲欧美日韩一区在线| 国产在线拍揄自揄拍无码视频| 国产精品色噜噜| 91免费视频网站在线观看| 亚洲成人一区| 国产精品在线看| 欧美亚洲韩国| 精品丝袜一区二区三区| 草视频在线观看| 中文字幕制服丝袜一区二区三区| 男人亚洲天堂网| 国产精品久久久久久久久久妞妞| 99精彩视频| 精品国产国产综合精品| 精品123区| 欧美一区二视频| 波多野结衣家庭教师在线观看| 97国产一区二区| 国产精品入口芒果| 欧美视频四区| 国产chinese精品一区二区| 国产日本亚洲| zzijzzij亚洲日本成熟少妇| 亚洲精品毛片一区二区三区| 懂色av中文一区二区三区天美| 免费不卡的av| 成人免费看视频| 99色这里只有精品| 99热在线精品观看| 国产精品中出一区二区三区| 粉嫩av一区二区| 久久久久一本一区二区青青蜜月| xxxwww在线观看| 精品国产乱码91久久久久久网站| 欧美日韩大片在线观看| 亚洲女子a中天字幕| 日韩av自拍偷拍| 国产在线视频精品一区| 好吊色这里只有精品| 欧美激情亚洲| 国产精品国产三级欧美二区| 成午夜精品一区二区三区软件| 欧美黄色片视频| 刘亦菲毛片一区二区三区| 亚洲成人av中文字幕| 日韩黄色三级视频| 欧美日韩在线视频观看| 无码 人妻 在线 视频| 日本一区二区免费在线观看视频| 牛夜精品久久久久久久| 国产综合色视频| 欧美a级免费视频| 国产亚洲在线| 天天综合狠狠精品| 久久久久久久久久久9不雅视频| 成人激情春色网| 风间由美性色一区二区三区四区| 亚洲91精品在线| 日韩高清成人| 久久精品久久久久久国产 免费| 国产伦精品一区二区三区视频痴汉| 日韩精品中文字幕一区二区三区| 国产精品99精品无码视| 欧美性少妇18aaaa视频| 超薄肉色丝袜一二三| 亚洲精品日日夜夜| 精品人妻一区二区三区香蕉| 中文字幕av在线一区二区三区| 午夜影院免费观看视频| www成人在线观看| 欧美大尺度做爰床戏| 国产福利精品一区二区| 少妇高潮喷水久久久久久久久久| 久久se精品一区精品二区| 久久久久久久香蕉| 久久亚洲欧美| 成人av在线播放观看| 日韩精品1区2区3区| 精品无码av无码免费专区| 久久av最新网址| 日韩最新中文字幕| 先锋影音久久久| 日本特级黄色大片| 亚洲欧美视频| 中国 免费 av| 久久久久久穴| 欧妇女乱妇女乱视频| 日韩精品久久理论片| 日韩美女爱爱视频| 国产传媒免费观看| 久久精品国产在热久久| 国产欧美日韩小视频| 日本中文一区二区三区| 日韩网站在线免费观看| 久久er99精品| 久久精品.com| 成人黄色一级视频| 91 视频免费观看| 欧美激情一区在线| 国产精品无码网站| 亚洲一区二区成人在线观看| 欧美激情亚洲色图| 欧美性20hd另类| 国产精品9191| 精品国产百合女同互慰| 亚洲无码精品国产| 日韩精品在线视频观看| www.日本在线观看| 久久亚洲春色中文字幕| 国产精品久久久久久妇女| 日本道色综合久久影院| 国产精品巨作av| 91精品黄色| 亚洲精品国产偷自在线观看| 午夜精品短视频| 日韩中文欧美在线| 青青草原av在线播放| 久久婷婷久久一区二区三区| 69亚洲乱人伦| 亚洲五月六月丁香激情| 中文字幕在线有码| 91麻豆精品国产综合久久久久久| 中文字幕码精品视频网站| 亚洲一区二区黄| 欧美黄色三级| 国产精品成久久久久三级| 精品在线91| 日本高清久久一区二区三区 | 久久久久久久有限公司| 影音先锋久久资源网| 欧美极品少妇无套实战| 国产精一区二区三区| 香蕉视频免费网站| 亚洲一二三四久久| 国产无套粉嫩白浆内谢| 亚洲国产精品国自产拍av秋霞| 韩国中文字幕hd久久精品| 久久免费国产视频| 亚洲精品亚洲人成在线观看| 老司机精品福利在线观看| 销魂美女一区二区三区视频在线| 免费av观看网址| 91麻豆视频网站| 日本少妇高潮喷水xxxxxxx| 色婷婷精品大视频在线蜜桃视频 | 91精品欧美久久久久久动漫 | 国产一区二区三区在线看麻豆 | av成人老司机| 男生裸体视频网站| 欧美亚洲综合网| 国产又粗又猛又爽| 欧美老少做受xxxx高潮| 9l视频自拍九色9l视频成人| 国产精品一区二区三区不卡| 亚洲影视在线| 五月婷婷深爱五月| 亚洲精品日产精品乱码不卡| 久久久久久久久久久久久久久久久| 亚洲精品mp4| 国产一区二区精品调教| 91系列在线播放| 亚洲日本欧美| 天天色综合社区| 一区二区三区四区五区视频在线观看 | 男人皇宫亚洲男人2020| 亚洲日本一区二区| 欧美日韩一区二区三区在线视频| 奇米影视在线99精品| 手机在线观看日韩av| 精品久久久久久久久久久久久久| 国产污视频网站| 欧美裸体xxxx极品少妇| 伊人春色之综合网| 中文字幕第50页| 久久久久久久久99精品| 在线免费日韩av|