Chciałbym włączyć buforowanie odpowiedzi Ajax w javascript / przeglądarce.
Domyślnie żądania są zawsze wysyłane, ale przeglądarka może udostępniać wyniki ze swojej pamięci podręcznej. Aby zabronić używania wyników z pamięci podręcznej, ustaw pamięć podręczną na wartość false. Aby żądanie zgłosiło błąd, jeśli zasób nie został zmodyfikowany od czasu ostatniego żądania, ustaw ifModified na true.
Jednak żaden z tych adresów nie wymusza buforowania.
Motywacja:
chcę umieścić $.ajax({...})
połączenia w moich funkcjach inicjalizacyjnych, z których niektóre żądają tego samego adresu URL. Czasami potrzebuję wywołać jedną z tych funkcji inicjalizacyjnych, czasami wywołuję kilka.
Dlatego chcę zminimalizować żądania do serwera, jeśli ten konkretny adres URL został już załadowany.
Mógłbym stworzyć własne rozwiązanie (z pewną trudnością!), Ale chciałbym wiedzieć, czy istnieje standardowy sposób zrobienia tego.
Odpowiedzi:
cache:true
działa tylko z żądaniem GET i HEAD.Możesz rzucić własne rozwiązanie, jak powiedziałeś, za pomocą czegoś w ten sposób:
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); }
Pracuję tu na skrzypcach
EDYCJA: ponieważ ten post staje się popularny, oto jeszcze lepsza odpowiedź dla tych, którzy chcą zarządzać pamięcią podręczną limitu czasu, a także nie musisz przejmować się całym bałaganem w $ .ajax (), ponieważ używam $ .ajaxPrefilter () . Teraz wystarczy tylko ustawienie
{cache: true}
, aby poprawnie obsłużyć pamięć podręczną: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); }
A skrzypce tutaj OSTROŻNIE, nie działają z $ .Odroczonym
Oto działająca, ale wadliwa implementacja działająca z odroczonym:
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 }); }); }); });
Fiddle HERE Niektóre problemy, nasz identyfikator pamięci podręcznej jest zależny od reprezentacji obiektu JSON json2 lib.
Użyj widoku konsoli (F12) lub FireBug, aby wyświetlić niektóre dzienniki wygenerowane przez pamięć podręczną.
źródło
localCache.set
funkcji? Dlaczego niedoSomehing(jqXHR)
po prostu po ustawieniu pamięci podręcznej?doSomething(localCache.set(url,jqXHR));
ale to tylko osobiste preferencjelocalCache.data[url] = { _: new Date().getTime(), data: _.cloneDeep(cachedData, true) }; _.cloneDeep(localCache.data[url].data, true)
Szukałem pamięci podręcznej do przechowywania aplikacji Phonegap i znalazłem odpowiedź @TecHunter, która jest świetna, ale zrobiona przy użyciu
localCache
.Znalazłem i dowiedziałem się, że localStorage to kolejna alternatywa dla buforowania danych zwracanych przez wywołanie ajax. Dlatego stworzyłem jedno demo,
localStorage
które pomoże innym, którzy mogą chcieć używaćlocalStorage
zamiastlocalCache
buforowania.Połączenie 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!"); } });
Aby przechowywać dane w 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 }; } });
Jeśli chcesz usunąć localStorage, użyj następującej instrukcji w dowolnym miejscu:
localStorage.removeItem("Info");
Mam nadzieję, że pomoże to innym!
źródło
localStorage.removeItem("Info");
, czy to"info"
jest adres URL?info
jest obiektem do przechowywania danych w localStorage.responseJSON is not defined
. Jakiś sposób to naprawić? (mój typ danych to html)Wszystkie nowoczesne przeglądarki zapewniają pamięć masową API. Możesz ich użyć (localStorage lub sessionStorage), aby zapisać swoje dane.
Wystarczy, że po otrzymaniu odpowiedzi zapiszesz ją w pamięci przeglądarki. Następnie następnym razem, gdy znajdziesz to samo połączenie, wyszukaj, czy odpowiedź została już zapisana. Jeśli tak, zwróć stamtąd odpowiedź; jeśli nie, wykonaj nowe połączenie.
Wtyczka Smartjax również robi podobne rzeczy; ale ponieważ Twoim wymaganiem jest po prostu zapisanie odpowiedzi na wywołanie, możesz napisać swój kod wewnątrz funkcji sukcesu jQuery ajax, aby zapisać odpowiedź. A przed wykonaniem połączenia sprawdź, czy odpowiedź jest już zapisana.
źródło
Jeśli zrozumiałem twoje pytanie, oto rozwiązanie:
$.ajaxSetup({ cache: true});
i dla konkretnych wezwań
$.ajax({ url: ..., type: "GET", cache: false, ... });
Jeśli chcesz odwrotnie (pamięć podręczna dla określonych połączeń), możesz ustawić false na początku i true dla określonych połączeń.
źródło
Stare pytanie, ale moje rozwiązanie jest nieco inne.
Pisałem pojedynczą stronę internetową, która nieustannie wykonywała wywołania Ajax wyzwalane przez użytkownika, a żeby było jeszcze trudniej, wymagało to bibliotek korzystających z metod innych niż jquery (takich jak dojo, natywne xhr itp.). Napisałem wtyczkę do jednej z moich własnych bibliotek aby buforować żądania Ajax tak wydajnie, jak to tylko możliwe, w sposób, który działałby we wszystkich głównych przeglądarkach, niezależnie od tego, które biblioteki były używane do wykonywania wywołania Ajax.
Rozwiązanie wykorzystuje jSQL (napisane przeze mnie - trwałą implementację SQL po stronie klienta napisane w javascript, która używa indexeddb i innych metod przechowywania danych) i jest dołączone do innej biblioteki o nazwie XHRCreep (napisanej przeze mnie), która jest całkowitym przepisaniem natywny obiekt XHR.
Aby zaimplementować wszystko, co musisz zrobić, umieść wtyczkę na swojej stronie, która jest tutaj .
Istnieją dwie możliwości:
jSQL.xhrCache.max_time = 60;
Ustaw maksymalny wiek w minutach. wszelkie starsze odpowiedzi z pamięci podręcznej są ponownie żądane. Wartość domyślna to 1 godzina.
jSQL.xhrCache.logging = true;
Po ustawieniu na true w konsoli zostaną pokazane pozorowane wywołania XHR do debugowania.
Możesz wyczyścić pamięć podręczną na dowolnej stronie za pośrednictwem
źródło
function getDatas() { let cacheKey = 'memories'; if (cacheKey in localStorage) { let datas = JSON.parse(localStorage.getItem(cacheKey)); // if expired if (datas['expires'] < Date.now()) { localStorage.removeItem(cacheKey); getDatas() } else { setDatas(datas); } } else { $.ajax({ "dataType": "json", "success": function(datas, textStatus, jqXHR) { let today = new Date(); datas['expires'] = today.setDate(today.getDate() + 7) // expires in next 7 days setDatas(datas); localStorage.setItem(cacheKey, JSON.stringify(datas)); }, "url": "http://localhost/phunsanit/snippets/PHP/json.json_encode.php", }); } } function setDatas(datas) { // display json as text $('#datasA').text(JSON.stringify(datas)); // your code here .... } // call getDatas();
wprowadź opis linku tutaj
źródło