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