Запобігання кешування браузера результатом виклику AJAX


262

Схоже, якщо я завантажую динамічний контент за допомогою $.get(), результат кешується в браузері.

Додавання довільної рядки в QueryString, здається, вирішує цю проблему (я використовую new Date().toString()), але це відчувається як хак.

Чи є якийсь інший спосіб досягти цього? Або якщо унікальний рядок - єдиний спосіб досягти цього, будь-які пропозиції, крім new Date()?


Ви можете використовувати короткі позначення $.now()замість того, щоб робити (нову дату (). GetTime ()) кожного разу.
Дейсон

1
Назва вашого запитання - це неправдивий оман. Ви можете розглянути можливість перейменування?
0112,

4
Чи розглядали ви обрати іншу відповідь як прийняту?
M4N

Відповіді:


241

Я використовую new Date().getTime(), що дозволить уникнути зіткнень, якщо у вас не буде декількох запитів у межах однієї мілісекунди:

$.get('/getdata?_=' + new Date().getTime(), function(data) {
    console.log(data); 
});

Редагувати: Ця відповідь вже кілька років. Він все ще працює (отже, я його не видалив), але є кращі / чистіші способи досягнення цього . Моя перевага - це цей метод, але ця відповідь також корисна, якщо ви хочете вимкнути кешування для кожного запиту протягом життя сторінки.


11
Я підкажу лише тому, що дозволити jQuery дозволити це робити, як у відповіді Пітера Дж. Ваше рішення спрацює, але складніше підтримувати в довгостроковій перспективі.
Ніклас Вульф

11
Яка частина цього потребує технічного обслуговування? У порівнянні з тим, що робить jQuery?
Сонячний Р Гупта

5
Може бути , варто відзначити , що new Date().getTime()код використовується як це ... var nocache = new Date().getTime(); var path = 'http://hostname.domain.tld/api/somejsonapi/?cache=' + nocache;. На це мені знадобилося кілька хвилин, щоб зрозуміти це. Звичайно, ?cacheможе бути будь-яке формулювання, якого API насправді не хоче.
подвійнийJ

1
+1 навіть відповідь Петра Дж, що краще підійде до цієї відповіді, не є помилковою, а також поганою. Я вважаю, що відеореєстратор зроблений тому, що ваш вище Петра (як прийнято). і ОП не з'являється на ЗП з початку 2013 року
Мішель Айрес

1
url = url + (-1 === url.indexOf('?') ? '?' : '&') + "__=" + Number(new Date());

513

Нижче наведено запобігання кешування всіх майбутніх запитів AJAX, незалежно від того, який метод jQuery ви використовуєте ($ .get, $ .ajax тощо)

$.ajaxSetup({ cache: false });

7
Після розслідування (Fiddler), схоже, jQuery реалізує це внутрішньо, просто додавши часову позначку в будь-якому випадку (про що йдеться в інших відповідях). Для мене метод .ajaxSetup чистіший (на мій погляд)
Петро J

8
Дійсно, це не повинно бути всередині документа, готового до виклику.
Пітер Дж

19
Навіщо відключати кеш-пам’ять Ajax у всьому світі? Я думаю, що це слід робити на основі дзвінка, як і відповідь Джонатана.
Сонячний Р Гупта

5
Що б не працювало для вашої програми. Я продовжую використовувати цей метод у комерційних додатках, коли мені абсолютно потрібні нові дані для всіх дзвінків AJAX. Для інших кешовані дані чудово.
Пітер Дж.

1
посилання Опис: Встановити значення за замовчуванням для майбутніх запитів на Ajax. Його використання не рекомендується.
itwebdeveloper

319

$ .Get () JQuery буде кешувати результати. Замість

$.get("myurl", myCallback)

ви повинні використовувати $ .ajax, що дозволить вам вимкнути кешування:

$.ajax({url: "myurl", success: myCallback, cache: false});

62
+1 Це правильна відповідь. Рішення Пітера Дж щодо глобального відключення кешування - це погана практика ІМО.
Салман фон Аббас

7
Важливо зазначити, що це лише "глобально" для сторінки / запиту.
Пітер Дж

3
+1: Кешування має бути визначеним для типу запиту. Деякі запити серверів можуть потребувати кешування (де дані сервера статичні), тому вибір кешування на основі запиту на основі запиту краще, ніж просто його вимкнення .
Пройшло кодування

1
+1 за правильну відповідь - запобігання кешування на основі дзвінка за допомогою методу jQuery, а не ручного злому.
Брендан-Хілл

2
Ще одна гарна відповідь. Треба сказати, для мене більшість часу глобальне відключення кешу принесло велику користь. Все залежить від того, як створено вашу програму. Немає срібної кулі, але в цій ситуації я рекомендував би функцію, яка приймає булеве значення для кешування, функцію зворотного виклику та URL-модульність. Посібник "хак" добре, але якщо ви використовуєте jQuery, дотримуйтесь їх функцій, коли це можливо. Це не тільки полегшить розвиток, але й надалі оновить бібліотеку.
Ентоні Мейсон

24

Усі відповіді тут залишають слід на запитуваній URL-адресі, яка відображатиметься в журналах доступу сервера.

Мені потрібне рішення на основі заголовка без побічного ефекту, і я виявив, що це можна досягти, встановивши заголовки, згадані в розділі Як контролювати кешування веб-сторінок у всіх браузерах? .

Результатом, що працює принаймні для Chrome, буде:

$.ajax({
   url: url, 
   headers: {
     'Cache-Control': 'no-cache, no-store, must-revalidate', 
     'Pragma': 'no-cache', 
     'Expires': '0'
   }
});


Можливо, дурне запитання, але якщо мій аякс поверне зображення, чи будуть зображення кешовані? Щоб уникнути масових запитів Amazon S3?
Марсело Агімовель

MarceloAgimóvel, це, на мій погляд, може бути окремим питанням SO.
Aidin

23

інший спосіб - не надавати заголовків кешу з боку сервера в коді, який генерує відповідь на виклик ajax:

response.setHeader( "Pragma", "no-cache" );
response.setHeader( "Cache-Control", "no-cache" );
response.setDateHeader( "Expires", 0 );

17
Неправильно. В IE заголовки НЕ-кеш ігноруються XMLHttpRequest викликів, як описано тут: stackoverflow.com/questions/244918 / ... The DateTime (або мій метод .ajaxSetup) є тільки рішення , які дійсно працюють.
Петро J

Я щойно вставив свою звичайну мантру без кешу, не вказано, що це специфічне для IE
miceuz

2
Це має вимкнути кешування для всіх браузерів: response.setHeader ("Кеш-контроль", "max-age = 0, не-кеш, не-магазин, пост-перевірка = 0, попередня перевірка = 0");
Кріс Броскі

13

Особисто я вважаю, що метод рядка запиту є більш надійним, ніж спроба встановити заголовки на сервері - немає гарантії, що проксі-сервер чи браузер все одно не будуть кешувати його (деякі браузери гірші за інші - не називають імен).

Зазвичай я використовую, Math.random()але не бачу нічого поганого у використанні дати (вам не слід робити запити AJAX досить швидко, щоб отримати одне і те ж значення двічі).


2
Поєднайте дату (). GetTime () разом з Math.random (), і ви повинні бути в безпечній частині. У бічній примітці Ext.Ajax також використовує getTime (), коли вказано disabledCaching.
vividos

12

Дотримуючись документації: http://api.jquery.com/jquery.ajax/

ви можете використовувати cacheмайно з:

$.ajax({
    method: "GET",
    url: "/Home/AddProduct?",
    data: { param1: value1, param2: value2},
    cache: false,
    success: function (result) {
        // TODO
    }
});

5

Звичайно, "методи кеш-розбивання" виконають роботу, але це відбудеться не в першу чергу, якби сервер вказав клієнту, що відповідь не слід кешувати. У деяких випадках корисно кешувати відповіді, а іноді ні. Нехай сервер вирішить правильний термін служби даних. Ви можете змінити його пізніше. Набагато простіше зробити з сервера, ніж з багатьох місць у вашому коді інтерфейсу.

Звичайно, це не допомагає, якщо у вас немає контролю над сервером.


5

Що з використанням запиту POST замість GET ...? (Що вам все-таки слід ...)


Я думаю, що це краще рішення, але, на жаль, я (якось) можу лише зробити GET запит. Отож, це нова дата (). GetTime () на даний момент.
Саламандер2007

Будь ласка, додайте пояснення до своєї відповіді, щоб інші могли дізнатися з неї - навіщо потрібен запит POST?
Ніко Хааз

5

Справжнє питання, чому вам потрібно, щоб це не було кешоване. Якщо його не слід кешувати, оскільки він постійно змінюється, сервер повинен вказати, щоб не кешувати ресурс. Якщо він просто змінюється іноді (оскільки один з ресурсів, від якого залежить, може змінитися), і якщо клієнтський код має про це знати, він може додати параметр манекена до URL-адреси, який обчислюється з певного хешу або останньої модифікованої дати цих ресурсів (це те, що ми робимо в ресурсах сценарію Microsoft Ajax, щоб їх можна було кешувати назавжди, але нові версії все ще можуть подаватися у міру їх появи). Якщо клієнт не може знати зміни, правильним способом має бути те, щоб сервер правильно обробляв HEAD-запити та повідомляв клієнту, чи використовувати кешовану версію чи ні. Мені здається, що додавати випадковий параметр або сказати від клієнта ніколи не кешувати, це неправильно, оскільки кешируемость є властивістю ресурсу сервера, і тому слід вирішити на стороні сервера. Ще одне питання, що потрібно задати собі, чи повинен цей ресурс реально обслуговуватися через GET або він повинен проходити через POST? Це питання семантики, але це також має наслідки для безпеки (є атаки, які працюють лише у тому випадку, якщо сервер дозволяє GET). POST не буде кешовано.


6
Що робити, якщо ви переглядаєте проксі-сервери, на яких ви не керуєте їх політикою кешування? що робити, якщо вашому додатку явно потрібно кожного разу робити новий запит? Відповідь на речі не завжди чітко вирізана чорно-біла, завжди є сірі ділянки.
7wp

Щоправда, це не завжди чіткий зріз. Але побачивши цю відповідь, змусило мене поставити під сумнів свої припущення і змусило мене знайти першопричину моєї проблеми. Це може бути не у всіх, але мені це допомогло. Якщо ви тут читаєте це, ви також повинні це врахувати.
Джонатан Тран

У цьому мені допомогли, за замовчуванням ResponseCaching було встановлено на рівні 60 м сервера. Змінили його на No-Cache, і він перестав кешувати клієнта.
mattygee

4

Можливо, вам слід подивитися на $ .ajax () замість цього (якщо ви використовуєте jQuery, як це виглядає). Погляньте на сторінку: http://docs.jquery.com/Ajax/jQuery.ajax#options та опцію "кеш".

Іншим підходом було б подивитися на те, як ви кешуєте речі на стороні сервера.


1
На жаль, після деякого розслідування використання $ .ajax () та встановлення кеша = false в основному зробить те саме. jQuery додасть деякий випадковий номер до рядка запитів, і він не перевірятиме наявність існуючих запитів. Тому я думаю, що використання $ .get () буде достатньо.
Саламандер2007

Ага гаразд. Ніколи не пробував цього, просто пам’ятав, що я щось про це бачив у документах :)
finpingvin

Навіть не потрібно використовувати $ .ajax. Просто використовуйте .ajaxSetup.
Peter J

3

Невелике доповнення до відмінних відповідей: Якщо ви працюєте з не-ajax резервним рішенням для користувачів без JavaScript, вам доведеться все-таки виправити ці заголовки на стороні сервера. Це неможливо, хоча я розумію тих, хто відмовляється від нього;)

Я впевнений, є ще одне запитання щодо SO, яке дасть вам повний набір заголовків, які відповідають. Я не зовсім засуджений відповідь на міцеус охоплює всі основи на 100%.


3

Для тих із вас, хто користується cacheопцією $.ajaxSetup()мобільного Safari, виявляється, що вам може знадобитися використовувати мітку часу для POST, оскільки мобільний Safari теж кешує це. Відповідно до документації щодо $.ajax()(на яку ви скеровані $.ajaxSetup()):

Встановлення кешу в хибне буде правильно працювати лише із запитами HEAD та GET. Він працює, додаючи "_ = {timestamp}" до параметрів GET. Параметр не потрібен для інших типів запитів, за винятком IE8, коли POST зроблено до URL-адреси, яку вже запросив GET.

Тож встановлення цього варіанту не допоможе вам у випадку, про який я згадував вище.


2

В основному просто додайте cache:false;в аякс, де ви думаєте, що зміст буде змінюватися в міру прогресу. І місце, де зміст звичаю не змінюється, може опустити це. Таким чином, ви отримаєте нову відповідь щоразу


2

Кешування Ajax Internet Explorer: що ви збираєтеся з цим зробити? пропонує три підходи:

  1. Додайте маркер перебору кешу до рядка запиту, наприклад? Date = [timetamp]. У jQuery та YUI ви можете сказати їм зробити це автоматично.
  2. Використовуйте POST замість GET
  3. Надішліть заголовок відповіді HTTP, який спеціально забороняє браузерам кешувати його

2

Тепер це легко зробити, включивши / відключивши опцію кешу у вашому запиті на ajax, саме так

$(function () {
    var url = 'your url goes here';
    $('#ajaxButton').click(function (e) {
        $.ajax({
            url: url,
            data: {
                test: 'value'
            },
                cache: true, //cache enabled, false to reverse
                complete: doSomething
            });
        });
    });
    //ToDo after ajax call finishes
    function doSomething(data) {
        console.log(data);
    }
});

3
Через 6 років ти надаєш таку ж відповідь, що і Джонатан? ಠ_ಠ
redent84

люди можуть сказати, що минуло 6 років після опублікування питання. І моя відповідь на це питання відрізняється від будь-якого іншого, не кажучи вже про те, що це правильний на сьогоднішній день. Відповідати на такі запитання не для "запитувача", це для громади та початківців! Дякуємо, що все-таки додали роз'яснення!
Омар Ель Дон

І яка різниця між вашим та цим stackoverflow.com/a/735084/469218 ?
redent84

можливо, це ясність, з точки зору новачка, який задає таке питання !!
Омар Ель Дон

1

Якщо ви використовуєте IE 9, то перед визначенням класу контролера вам потрібно використовувати наступне:

[OutputCache (NoStore = вірно, тривалість = 0, VaryByParam = "*")]

публічний клас TestController: контролер

Це запобіжить кешування браузера.

Деталі за цим посиланням: http://dougwilsonsa.wordpress.com/2011/04/29/disabling-ie9-ajax-response-caching-asp-net-mvc-3-jquery/

Насправді це вирішило моє питання.


1

Як сказав @Athasach, згідно з документами jQuery, $.ajaxSetup({cache:false}) вони не працюватимуть, крім запитів GET та HEAD.

Вам краще відправити назад Cache-Control: no-cache все одно заголовок зі свого сервера. Це забезпечує більш чітке розділення проблем.

Звичайно, це не працює для службових URL-адрес, які ви не належите до свого проекту. У цьому випадку ви можете розглянути можливість звернення до сторонньої служби з кодом сервера, а не викликати її з коду клієнта.


1

Якщо ви використовуєте .net ASP MVC, відключіть кешування дій контролера, додавши наступний атрибут у функції кінцевої точки:

[OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]

Чи можете ви пояснити це далі? Як цей масив стосується AJAX?
Ніко Хааз

Це не масив, а атрибут MVC Controller Action.
Маріус

0

додати заголовок

headers: {
                'Cache-Control':'no-cache'
            }

Будь ласка, додайте до своєї відповіді якесь пояснення, щоб інші могли дізнатися з неї - куди слід додавати такі заголовки?
Ніко Хааз

-3

додати Math.random() до URL-адреси запиту


2
Це дасть нестабільні результати.
aj.toulan

Math.random діятиме лише як праметер, як url? _ = [Math.Random ()], він не має нічого спільного з нестабільним результатом.
xiaoyifang

4
Я розумію, що ти робив. Я просто коментував, що Math.Random () іноді дасть вам те саме число двічі. Якщо ви заповнюєте свою систему невизначеностями, вони додаватимуться лише одна над одною.
aj.toulan
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.