Ajax關於readyState和status的討論

來源:互聯網
上載者:User

標籤:style   blog   http   color   java   使用   os   io   

熟悉web開發的程式員想必對Ajax也不會陌生。現在已經有很多js架構封裝了ajax實現,例如JQuery的ajax函數,調用起來非常方便。當然本文不打算講架構的使用,我們將從Ajax的javascript源碼實現開始。

Ajax源碼實現
var getXmlHttpRequest = function () {    if (window.XMLHttpRequest) {        //主流瀏覽器提供了XMLHttpRequest對象        return new XMLHttpRequest();    }    else if (window.ActiveXObject) {        //低版本的IE瀏覽器沒有提供XMLHttpRequest對象        //所以必須使用IE瀏覽器的特定實現ActiveXObject        return new ActiveXObject("Microsoft.XMLHTTP");    }};var xhr = getXmlHttpRequest();xhr.onreadystatechange = function () {    if (xhr.readyState === 4 && xhr.status === 200) {        //擷取成功後執行操作        //資料在xhr.responseText    }};xhr.open("TYPE", "URL", true);xhr.send(""); 

可以看到,xhr對象是通過onreadystatechange來監聽Ajax的最終完成情況,這裡也迎來了這次要重點討論的主角:readyState和status。

什麼是readyState

readyState是XMLHttpRequest對象的一個屬性,用來標識當前XMLHttpRequest對象處於什麼狀態。

readyState總共有5個狀態值,分別為0~4,每個值代表了不同的含義,如下表所示:

  0    未初始化狀態:此時,已經建立了一個XMLHttpRequest對象
  1  準備發送狀態:此時,已經調用了XMLHttpRequest對象的open方法,並且XMLHttpRequest對象已經準備好將一個請求發送到伺服器端
  2  已經發送狀態:此時,已經通過send方法把一個請求發送到伺服器端,但是還沒有收到一個響應
  3  正在接收狀態:此時,已經接收到HTTP回應標頭部資訊,但是訊息體部分還沒有完全接收到
  4  完成響應狀態:此時,已經完成了HTTP響應的接收
什麼是status

status是XMLHttpRequest對象的一個屬性,表示響應的HTTP狀態代碼。

在HTTP1.1協議下,HTTP狀態代碼總共可分為5大類,如下表所示:

  1XX    伺服器收到請求,需要繼續處理。例如101狀態代碼,表示伺服器將通知用戶端使用更高版本的HTTP協議。
  2XX    請求成功。例如200狀態代碼,表示請求所希望的回應標頭或資料體將隨此響應返回。
  3XX    重新導向。例如302狀態代碼,表示臨時重新導向,請求將包含一個新的URL地址,用戶端將對新的地址進行GET請求。
  4XX    用戶端錯誤。例如404狀態代碼,表示用戶端請求的資源不存在。
  5XX    伺服器錯誤。例如500狀態代碼,表示伺服器遇到了一個未曾預料的情況,導致了它無法完成響應,一般來說,這個問題會在程式碼出錯時出現。
拋出問題

為什麼onreadystatechange的函數實現要同時判斷readyState和status呢?

我們知道 readyState === 4 已經表示了請求響應成功了,為什麼還要後續的status呢?帶著問題,我們開始來做一些實驗吧。

只使用readyState判斷

javascript端的實現代碼如下:

var getXmlHttpRequest = function () {    if (window.XMLHttpRequest) {        return new XMLHttpRequest();    }    else if (window.ActiveXObject) {        return new ActiveXObject("Microsoft.XMLHTTP");    }};var xhr = getXmlHttpRequest();xhr.onreadystatechange = function () {    if (xhr.readyState === 4) {        alert(xhr.responseText);    }};xhr.open("GET", "/data.aspx", true);xhr.send("");

這個示範DEMO使用ASP.NET Webform架構,現在我們在後台data.aspx做一些手腳,不如讓它報錯試試!C#代碼如下:

public partial class data : System.Web.UI.Page{    protected void Page_Load(object sender, EventArgs e)    {        throw new Exception("Error");    }}

運行javascript代碼,提示視窗出現了如下:

服務響應出錯了,但還是返回了資訊,這並不是我們想要的結果。開啟Fiddler監控,可以看到data.aspx返回的是500響應,但由於只使用readystate做判斷,它不理會放回的結果是500還是200,只要響應成功返回了,就執行接下來的javascript代碼,結果將造成各種不可預料的錯誤。所以只使用readyState判斷是行不通的。

換另外一個角度想,狀態代碼返回200就表示這次響應是成功的了,那麼是不是可以不使用readyState,單獨只使用status做判斷呢?好,帶著問題,繼續來做實驗吧。

只使用status判斷

javascript端的代碼實現如下:

var getXmlHttpRequest = function () {    if (window.XMLHttpRequest) {        return new XMLHttpRequest();    }    else if (window.ActiveXObject) {        return new ActiveXObject("Microsoft.XMLHTTP");    }};var xhr = getXmlHttpRequest();xhr.onreadystatechange = function () {    if (xhr.status === 200) {        alert("readyState=" + xhr.readyState + xhr.responseText);    }};xhr.open("GET", "/data.aspx", true);xhr.send("");

這次將在data.aspx後台做處理,讓它只返回一個字串,實現如下:

public partial class data : System.Web.UI.Page{    protected void Page_Load(object sender, EventArgs e)    {        Response.Write("Test");        Response.End();    }}

一切都是那麼地自然,是不是只要彈出一個寫著一行"readyState=4Test"的字串的提示框,就表示結果成立了?把它跑起來了吧,結果已經就離我們不遠了!

事實上,結果卻不像預期那樣。響應碼確實是返回了200,但是總共彈出了3次視窗!第一次是“readyState=2”的視窗,第二次是“readyState=3Test”的視窗,第三次是“readyState=4Test”的視窗。由此,可見onreadystatechange函數的執行不是只在readyState變為4的時候觸發的,而是readyState的每次變化都會觸發,所以就出現了前面說的那種情況。可見,單獨使用status判斷也是行不通的。

進一步思考

由上面的實驗,我們可以知道判斷的時候readyState和status缺一不可。那麼readyState和status的先後判斷順序會不會有影響呢?我們可以將status調到前面先判斷,代碼如 xhr.status === 200 && xhr.readyState === 4。

事實上,這對於最終的結果是沒有影響的,但是中間的效能就不同了。由上一個實驗我們知道,readyState的每次變化都會觸發onreadystatechange函數,假如先判斷status,那麼每次都會多判斷一次status的狀態。雖然效能上影響甚微,不過我們還是應該抱著追求極致代碼的想法,把readyState的判斷放在前面。

如果你有新的想法,歡迎留言討論。

參考資料: 鋒利的JQuery, http狀態代碼維基百科

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.