在jquery的1.5版本中加了一個Deferred對象,jq的代碼也做了大規模重寫。如果想要了解該對象,推薦閱讀:jQuery Deferred對象詳細源碼分析(-)
jq的ajax方法也用Deferred對象加入了新特性,現在我們來使用ajax新特性來實現xhr的代理緩存,主要目的:避免重復請求。
注意:代理緩存主要用來cache從server拉取的數據,對於client發數據到server處理的情況不要使用
對同一url二次請求分為兩種情況
- 情況一:第一次請求還未完成,發出了第二次請求;
- 情況二:第一次請求已完成,再發出了第二次請求。
所以我們需要用到兩個對象,一個__xhrCache__保存jqXhr,一個__dataCache__保存請求的結果
var jqXhrCache = { __xhrCache__: {}, __dataCache__: {}, request: function(op, doneCallback, failCallback) { var url = typeof op === 'string' ? op : op.url, enUrl = encodeURIComponent(url), xca = this.__xhrCache__, dca = this.__dataCache__; if(!xca[enUrl]) { xca[enUrl] = $.ajax(op).done(function(data) { dca[enUrl] = data; }); } if(dca[enUrl] === undefined) {
/*情況一:將第二次請求的回調事件追加給緩存的jqXhr對象*/ xca[enUrl].done(doneCallback).fail(failCallback); } else {
/*情況二:代入緩存結果執行第二次請求的回調事件*/ doneCallback.call(null, dca[enUrl], xca[enUrl]); } return xca[enUrl]; } };
上面版本的不足之處是__xhrCache__和__dataCache__可能會被意外修改,雖然從命名上看起來像私有成員,但還是有被外界篡改的風險,那么下面使用閉包使它們真正私有化
var jqXhrCache = (function() { var __xhrCache__ = {}, __dataCache__ = {}; return { request: function(op, doneCallback, failCallback) { var url = typeof op === 'string' ? op : op.url, enUrl = encodeURIComponent(url), xca = __xhrCache__, dca = __dataCache__; if(!xca[enUrl]) { xca[enUrl] = $.ajax(op).done(function(data) { dca[enUrl] = data; }); } if(dca[enUrl] === undefined) { xca[enUrl].done(doneCallback).fail(failCallback); } else { doneCallback.call(null, dca[enUrl], xca[enUrl]); } return xca[enUrl]; } }; })();
到這里已經可以避免同一url的二次請求了,但這里cache對象在瀏覽器刷新或重新打開后又會被重置;如果需要長久保存請求的結果(如縣市資料等不經常變動的數據),可以考慮使用html5中的localStorage。
使用方法:jqXhrCache.request('/testDefer.html', function(data) { console.log(data) }, function() { console.log('request fail') });