jquery ajax使用代理缓存避免重复请求
在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') });