XMLHttpRequest是什么

小編給大家分享一下XMLHttpRequest是什么,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

創(chuàng)新互聯(lián)專注于旌陽企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè)公司,成都商城網(wǎng)站開發(fā)。旌陽網(wǎng)站建設(shè)公司,為旌陽等地區(qū)提供建站服務(wù)。全流程按需制作網(wǎng)站,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

Web 2.0 一瞥

我們需要一種方法使 發(fā)送的請(qǐng)求 和 接收的響應(yīng) 只包含需要的數(shù)據(jù)而不是整個(gè) HTML 頁面。

多數(shù)交互都是在已有頁面上增加細(xì)節(jié)、修改主體文本或者覆蓋原有數(shù)據(jù)。這些情況下,Ajax 和 Web 2.0 方法允許在不 更新整個(gè) HTML 頁面的情況下發(fā)送和接收數(shù)據(jù)。

XMLHttpRequest 簡介

XMLHttpRequest:一個(gè) JavaScript 對(duì)象,它是Web 2.0、Ajax 和大部分其他內(nèi)容的核心。下面給出將要用于該對(duì)象的很少的幾個(gè)方法和屬性:

open():建立到服務(wù)器的新請(qǐng)求。
send():向服務(wù)器發(fā)送請(qǐng)求。
abort():退出當(dāng)前請(qǐng)求。
readyState:提供當(dāng)前 HTML 的就緒狀態(tài)。
responseText:服務(wù)器返回的請(qǐng)求響應(yīng)文本。

用 XMLHttpRequest 做什么?
這些方法和屬性都與發(fā)送請(qǐng)求及處理響應(yīng)有關(guān)。事實(shí)上,如果看到 XMLHttpRequest 的所有方法和屬性,就會(huì)發(fā)現(xiàn)它們都 與非常簡單的請(qǐng)求/響應(yīng)模型有關(guān)。

首先需要?jiǎng)?chuàng)建一個(gè)新變量并賦給它一個(gè) XMLHttpRequest 對(duì)象實(shí)例。

清單 1. 創(chuàng)建新的 XMLHttpRequest 對(duì)象

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

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

清單 2. 創(chuàng)建 XMLHttpRequest 的 Java 偽代碼

XMLHttpRequest request = new XMLHttpRequest();

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

錯(cuò)誤處理

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

清單 3. 創(chuàng)建具有錯(cuò)誤處理能力的 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、創(chuàng)建一個(gè)新變量 request 并賦值 false。后面將使用 false 作為判定條件,它表示還沒有創(chuàng)建 XMLHttpRequest對(duì)象。
2、增加 try/catch 塊:
1)嘗試創(chuàng)建 XMLHttpRequest 對(duì)象。
2)如果失?。╟atch (failed))則保證 request 的值仍然為false。
3、檢查 request 是否仍為 false(如果一切正常就不會(huì)是 false)。
4、如果出現(xiàn)問題(request 是 false)則使用 JavaScript 警告通知用戶出現(xiàn)了問題。

現(xiàn)在已經(jīng)得到了一段帶有錯(cuò)誤檢查的 XMLHttpRequest 對(duì)象創(chuàng)建代碼,還可以告訴您哪兒出了問題。

應(yīng)付 Microsoft
我們需要采用不同的方法處理 Microsoft 瀏覽器。
清單 4. 增加對(duì) 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>

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

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

這樣修改代碼之后再使用 Internet Explorer 試驗(yàn),就應(yīng)該看到已經(jīng)創(chuàng)建的表單(沒有錯(cuò)誤消息)。

靜態(tài)與動(dòng)態(tài)

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

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

清單 5. 將 XMLHttpRequest 創(chuàng)建代碼移動(dò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();
      // 使用request變量進(jìn)行一系列的操作
    }
</script>

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

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

用 XMLHttpRequest 發(fā)送請(qǐng)求

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

歡迎使用沙箱

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

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

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

代碼創(chuàng)建了一個(gè)新變量 phone,并把 ID 為 “phone” 的表單字段的值賦給它。

清單 8 展示了這個(gè)表單的 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>你的訂單會(huì)被發(fā)送到:</p>
       <div id="address"></div>
       <p>你的訂單類型:</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)用戶輸入電話號(hào)碼或者改變電話號(hào)碼時(shí),將觸發(fā) 清單 8 所示的 getCustomerInfo() 方法。該方法取得電話號(hào)碼并構(gòu)造存儲(chǔ)在 url 變量中的 URL 字符串。記住,由于 Ajax 代碼是沙箱型的,因而只能連接到同一個(gè)域,實(shí)際上 URL 中不需要域名。該例中的腳本名為 /cgi-local/lookupCustomer.php。最后,電話號(hào)碼作為 GET 參數(shù)附加到該腳本中:”phone=” + escape(phone)。

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

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

打開請(qǐng)求

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

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

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

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

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

清單 9. 打開請(qǐng)求

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

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

挑戰(zhàn)異步性

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

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

而異步請(qǐng)求不 等待服務(wù)器響應(yīng)。發(fā)送請(qǐng)求后應(yīng)用程序繼續(xù)運(yùn)行。用戶仍然可以在 Web 表單中輸入數(shù)據(jù),甚至離開表單。服務(wù)器悄悄地響應(yīng)請(qǐng)求,完成后告訴原來的請(qǐng)求者工作已經(jīng)結(jié)束。

發(fā)送請(qǐng)求

一旦用 open() 配置好之后,就可以發(fā)送請(qǐng)求了。

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

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

雖然可以使用 send() 發(fā)送數(shù)據(jù),但也能通過 URL 本身發(fā)送數(shù)據(jù)。事實(shí)上,GET 請(qǐng)求(在典型的 Ajax 應(yīng)用中大約占 80%)中,用 URL 發(fā)送數(shù)據(jù)要容易得多。如果需要發(fā)送安全信息或 XML,可能要考慮使用 send() 發(fā)送內(nèi)容。如果不需要通過 send() 傳遞數(shù)據(jù),則只要傳遞 null 作為該方法的參數(shù)即可。

清單 10. 發(fā)送請(qǐng)求

   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);
   }

指定回調(diào)方法

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

首先一定要理解這些代碼中的流程(如果需要請(qǐng)回顧 清單 10)。建立其請(qǐng)求然后發(fā)出請(qǐng)求。此外,因?yàn)槭钱惒秸?qǐng)求,所以 JavaScript 方法(例子中的 getCustomerInfo())不會(huì)等待服務(wù)器。因此代碼將繼續(xù)執(zhí)行,就是說,將退出該方法而把控制返回給表單。用戶可以繼續(xù)輸入信息,應(yīng)用程序不會(huì)等待服務(wù)器。

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

在 JavaScript 中引用函數(shù):

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

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

   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);
   }

需要特別注意的是該屬性在代碼中設(shè)置的位置 —— 它是在調(diào)用 send() 之前 設(shè)置的。發(fā)送請(qǐng)求之前必須設(shè)置該屬性,這樣服務(wù)器在回答完成請(qǐng)求之后才能查看該屬性?,F(xiàn)在剩下的就只有編寫 updatePage() 方法了,這是本文最后一節(jié)要討論的重點(diǎn)。

處理服務(wù)器響應(yīng)

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

回調(diào)和 Ajax

現(xiàn)在我們已經(jīng)看到如何告訴服務(wù)器完成后應(yīng)該做什么:將 XMLHttpRequest 對(duì)象的 onreadystatechange 屬性設(shè)置為要運(yùn)行的函數(shù)名。這樣,當(dāng)服務(wù)器處理完請(qǐng)求后就會(huì)自動(dòng)調(diào)用該函數(shù)。也不需要擔(dān)心該函數(shù)的任何參數(shù)。我們從一個(gè)簡單的方法開始,如 清單 12 所示。

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

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

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

根據(jù)瀏覽器的不同,在表單停止彈出警告之前會(huì)看到兩次、三次甚至四次警告。這是怎么回事呢?原來我們還沒有考慮 HTTP 就緒狀態(tài),這是請(qǐng)求/響應(yīng)循環(huán)中的一個(gè)重要部分。

HTTP 就緒狀態(tài)

前面提到,服務(wù)器在完成請(qǐng)求之后會(huì)在 XMLHttpRequest 的 onreadystatechange 屬性中查找要調(diào)用的方法。這是真的,但還不完整。事實(shí)上,每當(dāng) HTTP 就緒狀態(tài)改變時(shí)它都會(huì)調(diào)用該方法。這意味著什么呢?首先必須理解 HTTP 就緒狀態(tài)。

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

0:請(qǐng)求沒有發(fā)出(在調(diào)用 open() 之前)。
1:請(qǐng)求已經(jīng)建立但還沒有發(fā)出(調(diào)用 send() 之前)。
2:請(qǐng)求已經(jīng)發(fā)出正在處理之中(這里通??梢詮捻憫?yīng)得到內(nèi)容頭部)。
3:請(qǐng)求已經(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,但實(shí)際上很少是這種情況。一些瀏覽器從不報(bào)告 0 或 1 而直接從 2 開始,然后是 3 和 4。其他瀏覽器則報(bào)告所有的狀態(tài)。還有一些則多次報(bào)告就緒狀態(tài) 1。在上一節(jié)中看到,服務(wù)器多次調(diào)用 updatePage(),每次調(diào)用都會(huì)彈出警告框 —— 可能和預(yù)期的不同!

對(duì)于 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)在就會(huì)看到與預(yù)期的一樣,只顯示一次警告信息了。

HTTP 狀態(tài)碼

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

比方說,您肯定遇到過輸入了錯(cuò)誤的 URL 請(qǐng)求而得到 404 錯(cuò)誤碼的情形,它表示該頁面不存在。這僅僅是 HTTP 請(qǐng)求能夠收到的眾多錯(cuò)誤碼中的一種。表示所訪問數(shù)據(jù)受到保護(hù)或者禁止訪問的 403 和 401 也很常見。無論哪種情況,這些錯(cuò)誤碼都是從完成的響應(yīng) 得到的。換句話說,服務(wù)器履行了請(qǐng)求(即 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ù)(而不是錯(cuò)誤或者其他有問題的信息)。因此還要在回調(diào)方法中增加狀態(tài)檢查,如 清單 14 所示。

清單 14. 檢查 HTTP 狀態(tài)碼

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

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

清單 15. 增加一點(diǎn)錯(cuò)誤檢查

   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);
   }

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

讀取響應(yīng)文本

現(xiàn)在可以確保請(qǐng)求已經(jīng)處理完成(通過就緒狀態(tài)),服務(wù)器給出了正常的響應(yīng)(通過狀態(tài)碼),最后我們可以處理服務(wù)器返回的數(shù)據(jù)了。返回的數(shù)據(jù)保存在 XMLHttpRequest 對(duì)象的 responseText 屬性中。

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

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

清單 16. 處理服務(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, "");
       } else
         alert("status is " + request.status);
     }
   }

首先,得到 responseText 并使用 JavaScript split() 方法從管道符分開。得到的數(shù)組放到 response 中。數(shù)組中的第一個(gè)值 —— 上一個(gè)訂單 —— 用 response[0] 訪問,被設(shè)置為 ID 為 “order” 的字段的值。第二個(gè)值 response[1],即客戶地址,則需要更多一點(diǎn)處理。因?yàn)榈刂分械男杏靡话愕男蟹指舴ā癨n”字符)分隔,代碼中需要用 XHTML 風(fēng)格的行分隔符
來代替。替換過程使用 replace() 函數(shù)和正則表達(dá)式完成。最后,修改后的文本作為 HTML 表單 div 中的內(nèi)部 HTML。結(jié)果就是表單突然用客戶信息更新了,如圖 4 所示。

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

結(jié)束語

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

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

因此不要忽略這些細(xì)節(jié)或者簡單地瀏覽一下,如果便捷華麗的工具箱出現(xiàn)了錯(cuò)誤,您就不必?fù)项^或者發(fā)送郵件請(qǐng)求支持了。如果了解如何直接使用 XMLHttpRequest,就會(huì)發(fā)現(xiàn)很容易調(diào)試和解決最奇怪的問題。只有讓其解決您的問題,工具箱才是好東西。

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

下一期文章中將進(jìn)一步討論該對(duì)象,探討它的一些更有趣的屬性(如 responseXML),以及如何使用 POST 請(qǐng)求和以不同的格式發(fā)送數(shù)據(jù)。

以上是XMLHttpRequest是什么的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

網(wǎng)站標(biāo)題:XMLHttpRequest是什么
文章出自:http://muchs.cn/article26/jcpdjg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動(dòng)態(tài)網(wǎng)站、網(wǎng)頁設(shè)計(jì)公司、企業(yè)網(wǎng)站制作、靜態(tài)網(wǎng)站商城網(wǎng)站、外貿(mào)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都app開發(fā)公司