我想在javascript /浏览器中启用ajax响应的缓存。
从jquery.ajaxdocs:
默认情况下,始终发出请求,但浏览器可能会在其缓存之外提供结果。要禁止使用缓存的结果,请将cache设置为false。如果自上次请求以来未修改资产,则导致请求报告失败,请将ifModified设置为true。
但是,这些地址都没有强制缓存。
动机: 我想$.ajax({...})在我的初始化函数中放入调用,其中一些请求相同的URL。有时我需要调用这些初始化函数之一,有时我调用多个初始化函数。
$.ajax({...})
因此,如果已经加载了特定的URL,我想最小化对服务器的请求。
我可以推出自己的解决方案(有些困难!),但是我想知道是否有标准的方法可以做到这一点。
cache:true 仅适用于GET和HEAD请求。
cache:true
您可以按照以下方式推出自己的解决方案:
var localCache = { data: {}, remove: function (url) { delete localCache.data[url]; }, exist: function (url) { return localCache.data.hasOwnProperty(url) && localCache.data[url] !== null; }, get: function (url) { console.log('Getting in cache for url' + url); return localCache.data[url]; }, set: function (url, cachedData, callback) { localCache.remove(url); localCache.data[url] = cachedData; if ($.isFunction(callback)) callback(cachedData); } }; $(function () { var url = '/echo/jsonp/'; $('#ajaxButton').click(function (e) { $.ajax({ url: url, data: { test: 'value' }, cache: true, beforeSend: function () { if (localCache.exist(url)) { doSomething(localCache.get(url)); return false; } return true; }, complete: function (jqXHR, textStatus) { localCache.set(url, jqXHR, doSomething); } }); }); }); function doSomething(data) { console.log(data); }
编辑:随着这篇文章的流行,对于那些想要管理超时缓存的人来说,这是一个更好的答案,而且当我使用$.ajaxPrefilter()时,您也不必费心$.ajax()中的所有混乱。。现在只需进行设置就足以正确处理缓存:{cache: true}
{cache: true}
var localCache = { /** * timeout for cache in millis * @type {number} */ timeout: 30000, /** * @type {{_: number, data: {}}} **/ data: {}, remove: function (url) { delete localCache.data[url]; }, exist: function (url) { return !!localCache.data[url] && ((new Date().getTime() - localCache.data[url]._) < localCache.timeout); }, get: function (url) { console.log('Getting in cache for url' + url); return localCache.data[url].data; }, set: function (url, cachedData, callback) { localCache.remove(url); localCache.data[url] = { _: new Date().getTime(), data: cachedData }; if ($.isFunction(callback)) callback(cachedData); } }; $.ajaxPrefilter(function (options, originalOptions, jqXHR) { if (options.cache) { var complete = originalOptions.complete || $.noop, url = originalOptions.url; //remove jQuery cache as we have our own localCache options.cache = false; options.beforeSend = function () { if (localCache.exist(url)) { complete(localCache.get(url)); return false; } return true; }; options.complete = function (data, textStatus) { localCache.set(url, data, complete); }; } }); $(function () { var url = '/echo/jsonp/'; $('#ajaxButton').click(function (e) { $.ajax({ url: url, data: { test: 'value' }, cache: true, complete: doSomething }); }); }); function doSomething(data) { console.log(data); }
这是一个可行但有缺陷的实现,与deferd一起使用:
var localCache = { /** * timeout for cache in millis * @type {number} */ timeout: 30000, /** * @type {{_: number, data: {}}} **/ data: {}, remove: function (url) { delete localCache.data[url]; }, exist: function (url) { return !!localCache.data[url] && ((new Date().getTime() - localCache.data[url]._) < localCache.timeout); }, get: function (url) { console.log('Getting in cache for url' + url); return localCache.data[url].data; }, set: function (url, cachedData, callback) { localCache.remove(url); localCache.data[url] = { _: new Date().getTime(), data: cachedData }; if ($.isFunction(callback)) callback(cachedData); } }; $.ajaxPrefilter(function (options, originalOptions, jqXHR) { if (options.cache) { //Here is our identifier for the cache. Maybe have a better, safer ID (it depends on the object string representation here) ? // on $.ajax call we could also set an ID in originalOptions var id = originalOptions.url+ JSON.stringify(originalOptions.data); options.cache = false; options.beforeSend = function () { if (!localCache.exist(id)) { jqXHR.promise().done(function (data, textStatus) { localCache.set(id, data); }); } return true; }; } }); $.ajaxTransport("+*", function (options, originalOptions, jqXHR, headers, completeCallback) { //same here, careful because options.url has already been through jQuery processing var id = originalOptions.url+ JSON.stringify(originalOptions.data); options.cache = false; if (localCache.exist(id)) { return { send: function (headers, completeCallback) { completeCallback(200, "OK", localCache.get(id)); }, abort: function () { /* abort code, nothing needed here I guess... */ } }; } }); $(function () { var url = '/echo/jsonp/'; $('#ajaxButton').click(function (e) { $.ajax({ url: url, data: { test: 'value' }, cache: true }).done(function (data, status, jq) { console.debug({ data: data, status: status, jqXHR: jq }); }); }); });
有些问题,我们的缓存ID取决于json2 lib JSON对象表示形式。
使用控制台视图(F12)或FireBug查看由缓存生成的某些日志。