原來覺得ifModified是爲了在AJAX請求是發送 If-Modified-Since頭,讓服務端返回304。html
測試代碼以下:jquery
$(function () { test(); window.setTimeout(test, 5000); }); function test() { $.ajax({ type: "GET", url: url, ifModified: true, success: function (d, textStatus, xhr) { console.log(xhr.status); console.log(d == undefined); } }); }
chrome:ajax
network 爲 304,304chrome
console爲 200 false, 304 trueapi
ie10瀏覽器
network爲 304, 304緩存
console爲 200 false, 304 true服務器
firefox:app
network爲 304, 200(from cache)ide
console爲 200 false, 200 false
上述測試是創建在已經訪問過的基礎上進行的,所以第一個請求都爲304。
測試結果有幾個疑問
一、爲何network監控的響應碼與jqXHR.status有不一致的狀況
二、chrome與ie10爲何第一次請求能夠獲取到內容,但一樣的304返回,第二次卻內容爲undefined
三、firefox的第二次請求爲何直接從cache取數據
據文檔 XHR API
For 304 Not Modified
responses that are a result of a user agent generated conditional request the user agent must act as if the server gave a 200 OK
response with the appropriate content. The user agent must allow setRequestHeader()
to override automatic cache validation by setting request headers (e.g., If-None-Match
, If-Modified-Since
), in which case 304 Not Modified
responses must be passed through.
就是說通常狀況下,若是服務器返回304後,瀏覽器會進行轉換。此時jqXHR.status應該是200,而且瀏覽器會自動將緩存的內容發送給jqXHR(304,服務器是不會發送內容信息的);
但能夠經過jqXHR.setRequestHeader(If-Modified-Since)
來重載該行爲,若是服務端會返回304,則把該結果直接傳遞給 jqXHR。
據此咱們回答了第一個疑問。
那麼第二個問題是怎麼回事?
查看了network中的請求,二次請求都有帶 If-Modified-Since 的頭,沒什麼發現
在jq的源碼發現瞭如下代碼
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. if ( s.ifModified ) { if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) { jQuery.lastModified[ ifModifiedKey ] = lastModified; } if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) { jQuery.etag[ ifModifiedKey ] = etag; } }
這是從響應獲取Last-Modified頭的過程
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. if ( s.ifModified ) { ifModifiedKey = ifModifiedKey || s.url; if ( jQuery.lastModified[ ifModifiedKey ] ) { jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] ); } if ( jQuery.etag[ ifModifiedKey ] ) { jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] ); } }
這是設置If-Modified-Since頭的過程
回到主題 ifModified 參數,文檔以下
Allow the request to be successful only if the response has changed since the last request. This is done by checking the Last-Modified header. Default value is false
, ignoring the header. In jQuery 1.4 this technique also checks the 'etag' specified by the server to catch unmodified data.
文檔說得不是很清楚,看代碼的實現。
jq根據jQuery.lastModified字典中是否包含數據來決定是否設置If-Modified-Since。那第一次請求jQuery.lastModified是沒有數據的(JS是沒法獲取瀏覽器緩存的信息),所以第一次請求jqXHR是沒有設置If-Modified-Since,那也就解釋了第一次請求jqXHR.status爲200。由於有了第一次請求,jq獲取獲取到第一次請求響應中的Last-ModifiedjQuery.lastModified有了數據,第二次請求jqXHR是會加上If-Modified-Since頭的,所以jqXHR.status收到了瀏覽器直接傳遞過來的請求響應及內容。
搞定了第二個疑問。
第三個問題看了一些文檔尚未明確的結論,估計是firefox在xhr在處理cache上有些不一樣,服務器響應頭有包含
Cache-Control:public, max-age=18000
總結下:
jquery ifModified參數主要是爲了在經過JS檢測資源是否發生變化(304),而且在頁面的第一個AJAX請求jqXHR.status永遠不會返回304。
參考文檔