Кэширование ответа jQuery ajax в javascript / браузере
Я хотел бы включить кэширование ответа ajax в javascript / браузере.
по умолчанию запросы всегда выдаются, но браузер может служить
результаты из кэша. Чтобы запретить использование кэшированных результатов, установите
кэш в значение false. Чтобы вызвать запрос на сообщение об ошибке, если актив
не был изменен с момента последнего запроса, установите ifModified в true.
однако, ни из этих адресов принудительное кэширование.
мотивация:
Я хочу поставить $.ajax({...}) вызывает мои функции инициализации, некоторые из которых запрашивают один и тот же url. Иногда мне нужно вызвать одну из этих функций инициализации, иногда я называю несколько.
Итак, я хочу минимизировать запросы к серверу, если этот конкретный url-адрес уже загружен.
Я мог бы свернуть свое собственное решение (с некоторым трудом!), но я хотел бы знать если есть стандартный способ сделать это.
5 ответов:
cache:trueработает только с запросом GET и HEAD.вы могли бы свернуть свое собственное решение, как вы сказали, с чем-то вроде этих строк :
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); }EDIT: поскольку этот пост становится популярным, вот еще лучший ответ для тех, кто хочет управлять таймаутом кэша, и Вам также не придется беспокоиться обо всем беспорядке в $.ajax () как я использую $.ajaxPrefilter (). Теперь просто установка
{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); }а скрипка тутосторожно, не работает с $.Отложено
вот рабочая, но ошибочная реализация, работающая с отсрочкой:
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 }); }); }); });скрипка здесь Некоторые проблемы, наш идентификатор кэша зависит от представления объекта json2 lib JSON.
используйте Console view (F12) или FireBug для просмотра некоторых журналов, созданных кэшем.
Я искал кэширование для моего хранилища приложений phonegap, и я нашел ответ @TecHunter, который отлично подходит, но делается с помощью
localCache.Я нашел и узнал, что localStorage-это еще одна альтернатива для кэширования данных, возвращаемых вызовом ajax. Итак, я создал одну демо-версию с помощью
localStorageчто поможет другим, кто может захотеть использоватьlocalStorageвместоlocalCacheдля кэширования.Ajax Вызов:
$.ajax({ type: "POST", dataType: 'json', contentType: "application/json; charset=utf-8", url: url, data: '{"Id":"' + Id + '"}', cache: true, //It must "true" if you want to cache else "false" //async: false, success: function (data) { var resData = JSON.parse(data); var Info = resData.Info; if (Info) { customerName = Info.FirstName; } }, error: function (xhr, textStatus, error) { alert("Error Happened!"); } });для хранения данных в localStorage:
$.ajaxPrefilter(function (options, originalOptions, jqXHR) { if (options.cache) { var success = originalOptions.success || $.noop, url = originalOptions.url; options.cache = false; //remove jQuery cache as we have our own localStorage options.beforeSend = function () { if (localStorage.getItem(url)) { success(localStorage.getItem(url)); return false; } return true; }; options.success = function (data, textStatus) { var responseData = JSON.stringify(data.responseJSON); localStorage.setItem(url, responseData); if ($.isFunction(success)) success(responseJSON); //call back to original ajax call }; } });если вы хотите удалить localStorage, используйте следующий оператор везде, где вы хотите:
localStorage.removeItem("Info");надеюсь, что это помогает другим!
все современные браузеры предоставляют вам API хранения. Вы можете использовать их (localStorage или sessionStorage) для сохранения ваших данных.
все, что вам нужно сделать, это после получения ответа сохранить его в хранилище браузера. Затем в следующий раз, когда вы найдете тот же вызов, выполните поиск, если ответ уже сохранен. Если да, то верните ответ оттуда; если не сделать новый вызов.
Smartjax плагин также делает подобные вещи; но как ваше требование просто сохранение вызова ответ, вы можете написать свой код внутри функции успеха jQuery ajax, чтобы сохранить ответ. И перед тем, как позвонить просто проверить, если ответ уже сохранен.
Если я понял ваш вопрос, то вот решение :
$.ajaxSetup({ cache: true});и для конкретных вызовов
$.ajax({ url: ..., type: "GET", cache: false, ... });Если вы хотите противоположное (кэш для конкретных вызовов), вы можете установить false в начале и true для конкретных вызовов.
старый вопрос, но мое решение немного отличается.
я писал одностраничное веб-приложение, которое постоянно вызывало вызовы ajax, инициируемые пользователем, и чтобы сделать его еще более сложным, требовались библиотеки, которые использовали методы, отличные от jquery (например, dojo, native xhr и т. д.). Я написал плагин для одного из мои собственные библиотеки кэшировать запросы ajax максимально эффективно таким образом, чтобы они работали во всех основных браузерах, независимо от того, какие библиотеки были используется для вызова ajax.
решение использует jSQL (написанная мной-клиентская постоянная реализация SQL, написанная на javascript, которая использует indexeddb и другие методы хранения dom) и поставляется в комплекте с другой библиотекой под названием XHRCreep (написано мной), который является полной перезаписью собственного объекта XHR.
чтобы реализовать все, что вам нужно сделать, это включить плагин в вашу страницу, что здесь.
есть два варианта:
jSQL.xhrCache.max_time = 60;задать максимальный возраст в минутах. все кэшированные ответы, которые старше этого, запрашиваются повторно. По умолчанию-1 час.
jSQL.xhrCache.logging = true;если установлено значение true, в консоли для отладки будут отображаться макетные вызовы XHR.
вы можете очистить кэш на любой странице через
jSQL.tables = {}; jSQL.persist();
Comments