天天看點

ajax和它的逾時

日常開發中一般都會使得ajax去獲了資料,但有兩點是需要值得注意的:

1、ajax請求隊列

2、ajax的逾時處理

為什麼要注意這兩點?為了讓使用者在其可視區域内更快速的看見内容。

假設頁面結構分為三欄:左、中、右,而且頁面資料會比較多,頁面呈現的順序則是是按從上而下執行的(當然是從左至右開始,一個子產品一個子產品加載資料),如果不采用隊列,那麼在頁面可視範圍之外的子產品可能已經加載完資料了,而可視範圍之内(假設為第一屏)的子產品卻尚未開始接收資料,這一類應用如:搜狐部落格、新浪部落格、網易部落格等…

從ajax建立開始,這裡優化的一點是針對IE浏覽器,隻循環擷取一次使用哪種MSXML庫,副作用就是需要使用額外的屬性來記錄它

建立的xhr對象,它對應有5狀态(readyState屬性)

0   Uninitialized(尚未調用open方法)

1   Loading (已調用open,尚未調用send)

2   Loaded (已經調用send,尚未接收到響應)

3   Interactive (開始接收資料)

4   Complete (資料接收完畢,響應内容解析完成)

在判定一個請求是否已經完成的時候,驗證xhr的status有一點是需要注意的:“有的浏覽器會錯誤地傳回204狀态碼”,而IE(非原生的XHR對象)中會将204設定為1223,Opera會在取得204時将status設定為0,而Safari 3之前的版本會将status設定為undefined

最終驗證請求是否成功的代碼将會是:

( xhr.status >= 200 && xhr.status < 300 ) ||

xhr.status === 304 || xhr.status === 1223 || xhr.status === 0

另外在send的時候,還需要注意的是如果不需要通過請求主體發送資料,最好是傳入參數,因為send方法的參數

對于有些浏覽器是必需的,建議一般傳null即可

在發送請求時,可以通過setRequestHeader來設定HTTP頭部資訊,在使用GET請求時,可以在頭部加上If-Modified-Since、Cache-Control參數來達到重新整理緩存資料的目的(如果采用在URL上加随機資料或是時間戳,資源并沒有被緩存)

xhr.setRequestHeader('If-Modified-Since', 'Thu, 1 Jan 1970 00:00:00 GMT');

xhr.setRequestHeader('Cache-Control', 'no-cache');

在響應完成後,可以使用getResponseHeader、getAllResponseHeaders兩個方法來擷取指定或是全部的響應頭的HTTP資訊

剩下的一個問題是,處理ajax逾時的問題。jquery中的做法是使用定時器來檢測xhr的狀态,而使用延時器來解決逾時的問題:

setInterval(onreadystatechange, 13);

setTimeout(fn, timeout);

而在自定義的onreadystatechange函數中會檢測傳入的參數,如果參數為“timeout”則說明逾時了,先調用xhr的abort取消請求,然後再調用complete方法。至于間隔時間為什麼是13,這個沒仔細去研究它

正常情況下,如果readyState為4,則先清除定時器,然後再檢測響應的資料。而setTimeout中的fn函數,在處理時會先檢測請求是否已經處理過了,這裡它并沒有對延時器進行引用,會導緻的一種情況是,請求已經結束,延時器還在跑,直到達到指定的時間間隔。

最後如果ajax請求為異步的話,别忘記将xhr置為null==>xhr = null; 以防止記憶體洩漏的問題

IE8中直接寫xhr.timeout = xxx;然後當逾時時,會調用xhr的ontimeout方法,不過需要注意的問題是,當調用ontimeout事件時,此時的readyState可能已經變為了4,此時如果去通路status則會導緻錯誤(最好使用try{}catch{}進行捕獲一下)

到目前為止,除IE外,其它浏覽器支援xhr對象的onload事件,隻要浏覽器開始接收到響應,就會觸發它,是以在這個函數裡面還是需要對它的status屬性進行判斷。

最後一點是在FF 1.5之後,它支援progress事件,這意味着可以顯示目前請求的進度(不再是枯燥的loading了)。

在onprogress事件中會傳入一個event對象,它的target是對應的xhr對象,它包含了兩個額外的屬性:position、totalSize。

其中position表示已接收的位元組數,totalSize表示根據Content-Length響應頭部确定的預期位元組數。

var xhr = new createXHR();

xhr.onload = function() {

//...

}

xhr.onprogress = function(evt) {

var percent = (evt.position / evt.totalSize)*100;

xhr.open("get", url, true);

xhr.send(null);

繼續閱讀