国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項超值服

開通VIP
第 2 部分 使用 JavaScript 和 Ajax 發(fā)出異步請求(2)

清單 5. 將 XMLHttpRequest 創(chuàng)建代碼移動到方法中

<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 之前需要調(diào)用該方法。因此還需要 清單 6 這樣的代碼。

清單 6. 使用 XMLHttpRequest 的創(chuàng)建方法

<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>

 

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

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

用 XMLHttpRequest 發(fā)送請求

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

歡迎使用沙箱

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

設(shè)置服務(wù)器 URL

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

清單 7. 建立請求 URL

這里沒有難懂的地方。首先,代碼創(chuàng)建了一個新變量 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 to:</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>

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

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

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

打開請求

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

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

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

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

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

清單 9. 打開請求

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

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

挑戰(zhàn)異步性

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

·沙漏(特別是 Windows 上)。
·旋轉(zhuǎn)的皮球(通常在 Mac 機(jī)器上)。
·應(yīng)用程序基本上凍結(jié)了,然后過一段時間光標(biāo)變化了。

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

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

發(fā)送請求

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

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

var url = "/cgi-local/lookupCustomer.php?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ā)送請求

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

指定回調(diào)方法

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

清單 11. 設(shè)置回調(diào)方法

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

需要特別注意的是該屬性在代碼中設(shè)置的位置 —— 它是在調(diào)用 send() 之前設(shè)置的。發(fā)送請求之前必須設(shè)置該屬性,這樣服務(wù)器在回答完成請求之后才能查看該屬性。現(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è)置為要運(yùn)行的函數(shù)名。這樣,當(dāng)服務(wù)器處理完請求后就會自動調(diào)用該函數(shù)。也不需要擔(dān)心該函數(shù)的任何參數(shù)。我們從一個簡單的方法開始,如清單 12 所示。

清單 12. 回調(diào)方法的代碼

它僅僅發(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)用的方法。這是真的,但還不完整。事實上,每當(dāng) 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)中通常有部分?jǐn)?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)

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

修改后就可以保證服務(wù)器的處理已經(jīng)完成。嘗試運(yùn)行新版本的 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ù)受到保護(hù)或者禁止訪問的 403 和 401 也很常見。無論哪種情況,這些錯誤碼都是從完成的響應(yīng)得到的。換句話說,服務(wù)器履行了請求(即 HTTP 就緒狀態(tài)是 4)但是沒有返回客戶機(jī)預(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)碼

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

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

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
使用JavaScript 和Ajax 發(fā)出異步請求(一)
Ajax 中的高級請求和響應(yīng)(1)
Ext.Ajax.request使用說明
iframe創(chuàng)建智能表單-Javascript/Ajax-網(wǎng)頁制作-網(wǎng)頁教學(xué)網(wǎng)
掌握 ajax,第 1 部分: ajax 簡介
掌握 Ajax,第 3 部分: Ajax 中的高級請求和響應(yīng)(1)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服