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

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

Кажется, что добавление случайной строки в QueryString решает эту проблему (я использую new Date().toString()), но это похоже на взлом.

Есть ли другой способ добиться этого? Или, если уникальная строка - единственный способ добиться этого, любые предложения, кроме new Date()?


person Salamander2007    schedule 15.12.2008    source источник
comment
Вы можете использовать сокращенное обозначение $.now() вместо того, чтобы каждый раз выполнять (new Date (). GetTime ()).   -  person Dayson    schedule 01.07.2011
comment
Рассматривали ли вы выбор другого ответа в качестве принятого?   -  person M4N    schedule 22.07.2015


Ответы (21)


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

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

Изменить: этому ответу несколько лет назад. Он по-прежнему работает (следовательно, я не удалял его), но сейчас есть лучшие / более чистые способы достижения этого. Я предпочитаю этот метод, но этот ответ также полезен, если вы хотите отключить кеширование для каждого запроса во время существования страницы.

person Mark Bell    schedule 15.12.2008
comment
Я буду отрицать только потому, что это будет проще, если jQuery сделает это, как в ответе Питера Дж. Ваше решение будет работать, но его труднее поддерживать в долгосрочной перспективе. - person Niklas Wulff; 13.01.2011
comment
Какая часть этого требует обслуживания? По сравнению с тем, что делает jQuery? - person Sunny R Gupta; 30.05.2013
comment
Возможно, стоит отметить, что код new Date().getTime() используется вот так ..._ 2_. Мне потребовалось несколько минут, чтобы самому понять это. Конечно ?cache может быть любой формулировкой, которая на самом деле не нужна API. - person doubleJ; 10.07.2013
comment
+1 даже ответ Питера Дж., имея лучший подход, этот ответ не является неправильным и плохим. Я считаю, что DV сделаны, потому что ваш выше Питера (как принято). и OP не появляется на SO с начала 2013 года - person Michel Ayres; 05.09.2014
comment
Это единственный способ сработал для меня .. в FF .. Отличная техника. спасибо - person Girish Thimmegowda; 04.10.2015
comment
@ salamander2007 Это недопустимый ответ, cache: false - правильный подход в JQuery. - person user692942; 20.07.2020
comment
cache: false jQuery делает то же самое, т. е. добавляет к запросу параметр _={{timestamp}} GET: api.jquery. com / jquery.ajax Вместо магии jQuery, скрытой за сценой, этот ответ более ясен. - person onurmatik; 18.05.2021

Следующее предотвратит кэширование всех будущих запросов AJAX, независимо от того, какой метод jQuery вы используете ($ .get, $ .ajax и т. Д.)

$.ajaxSetup({ cache: false });
person Peter J    schedule 09.04.2009
comment
После расследования (Fiddler) похоже, что jQuery реализует это внутренне, просто добавляя временную метку в любом случае (как обсуждается в другом месте в этих ответах). Для меня метод .ajaxSetup чище (на мой взгляд). - person Peter J; 30.01.2010
comment
Почему это должно быть внутри вызова готовности документа? Как я могу быть уверен, что ни один из моих других обработчиков готовых документов (с вызовами ajax) не сработает раньше этого? - person Michiel Cornille; 28.06.2011
comment
На самом деле это не обязательно должно быть внутри вызова готовности документа. - person Peter J; 16.07.2011
comment
где нам нужно разместить этот фрагмент кода? И нужно ли нам размещать это на каждой странице, которая вызывает $ .ajax? - person Niar; 16.02.2013
comment
Поместите код так, чтобы он вызывался один раз при загрузке страницы, перед любым вызовом $ .ajax. - person Peter J; 16.02.2013
comment
Зачем отключать кеширование ajax глобально? Я думаю, что это должно быть сделано для каждого звонка, как то, что делает ответ Джонатана. - person Sunny R Gupta; 30.05.2013
comment
Ты прав. Если вы хотите контролировать кеширование для каждого запроса отдельно, а не глобально для всех запросов на странице, дерзайте! - person Peter J; 30.05.2013
comment
Этот ответ отлично подходит для меня. Но у меня есть одно сомнение, у меня много функций javascript на одной странице jsp, каждая функция будет внутренне вызывать вызов ajax. Так нужно ли мне писать код в вашем ответе во всех функциях? - person Kishan_KP; 14.07.2013
comment
Нет, один раз при загрузке страницы. - person Peter J; 15.07.2013
comment
Все, что работает для вашего приложения. Я продолжаю использовать этот метод в коммерческих приложениях, когда мне абсолютно необходимы свежие данные для всех вызовов AJAX. Для других подойдут кэшированные данные. - person Peter J; 05.09.2013
comment
С одной стороны, Петр прав. С другой стороны, недостатком этого подхода является то, что какой-нибудь младший разработчик или ужасный старший разработчик может в конечном итоге потратить много времени, пытаясь выяснить, почему их вызов кешируется; и не осознают, что это делается глобально. Очень плохо, они могут в конечном итоге использовать глобальный сеттер для установки другого глобального сеттера, думая, что это способ сделать это. Игра с глобальной переменной похожа на танец газа возле огня. - person Phil; 08.02.2014
comment
Объект AJAX jQuery будет следовать перенаправлениям, поэтому даже если вы отключите кеширование глобально, параметр "_={timestamp}", который jQuery добавляет для блокировки кеша браузера, может не перенаправляться с перенаправлением. В этом случае ваш запрос все еще может быть кеширован браузером. Решение состоит в том, чтобы либо убедиться, что вместе с перенаправлениями передается специальный параметр, либо вы отключите кеширование в коде на стороне сервера для этих запросов. (Например, gist.github.com/chrisbloom7/) - person Chris Bloom; 09.09.2014
comment
ссылка Описание: установка значений по умолчанию для будущих запросов Ajax. Его использование не рекомендуется. - person itwebdeveloper; 11.08.2015
comment
Если вы беспокоитесь о влиянии кеширования статического содержимого, jQuery не предотвратит этого, если вы явно не загружаете скрипты и стили через $ .get или тому подобное. Если вы работаете с частичными представлениями, получением ajax и т. П., Я настоятельно рекомендую вам реализовать это решение, иначе все может стать волосатым. Я считаю, что проще всего сбросить это на страницу макета / эталона, чтобы не было избыточности. - person Anthony Mason; 23.05.2016
comment
Наверное, браузер UC не поддерживает эту опцию. - person The_ehT; 11.08.2016

JQuery $ .get () кэширует результаты. Вместо того

$.get("myurl", myCallback)

вы должны использовать $ .ajax, что позволит вам отключить кеширование:

$.ajax({url: "myurl", success: myCallback, cache: false});
person Jonathan Moffatt    schedule 09.04.2009
comment
+1 Это правильный ответ. Решение Питера Дж по глобальному отключению кеширования - это плохая практика IMO. - person Salman von Abbas; 19.04.2012
comment
Важно отметить, что он глобален только для страницы / запроса. - person Peter J; 09.05.2012
comment
+1: кеширование должно зависеть от типа запроса. Некоторым запросам сервера может потребоваться кеширование (где данные сервера статичны), поэтому выбор кеширования по принципу запрос за запросом лучше, чем просто отключение всего этого. - person Gone Coding; 04.09.2013
comment
+1 за правильный ответ - предотвращение кеширования для каждого вызова с использованием метода jQuery, а не ручного взлома. - person Brendan Hill; 17.01.2014
comment
Еще один хороший ответ. Я должен сказать, что для меня большую часть времени глобальное отключение кеша было большим преимуществом. Однако все зависит от того, как разработано ваше приложение. Нет серебряной пули, но в этой ситуации я бы порекомендовал функцию, которая принимает логическое значение для кеширования, функцию для обратного вызова и URL-адрес для модульности. Ручной взлом - это нормально, но если вы используете jQuery, по возможности придерживайтесь их функций. Это не только упростит разработку сейчас, но и сделает будущие обновления библиотеки. - person Anthony Mason; 23.05.2016
comment
JQuery $ .get () кэширует результаты не совсем верно; использовать кешированный результат может браузер, а не jQuery. При использовании $.ajax с cache: false jQuery добавляет метку времени к URL-адресу, что обеспечивает свежий ответ от сервера. - person DigitalDan; 02.01.2018
comment
Лучший ответ, имо. В качестве примера предположим, что вам нужно сделать серию вызовов ajax для одного и того же URL-адреса (например, коннектора). В большинстве случаев нужно сделать только первую с отключенным кешем. - person Bob Ray; 24.09.2018

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

Мне нужно было решение на основе заголовков без побочных эффектов, и я обнаружил, что этого можно добиться, настроив заголовки, упомянутые в Как управлять кэшированием веб-страниц во всех браузерах?.

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

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

person Aidin    schedule 21.09.2016
comment
Может быть, глупый вопрос, но если мои изображения ajax вернут, будут ли изображения кешироваться? Чтобы избежать массовых запросов Amazon S3? - person Marcelo Agimóvel; 04.07.2018
comment
Марсело Агимовел, я считаю, что это может быть отдельный ТАК вопрос. - person Aidin; 01.06.2019

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

response.setHeader( "Pragma", "no-cache" );
response.setHeader( "Cache-Control", "no-cache" );
response.setDateHeader( "Expires", 0 );
person miceuz    schedule 15.12.2008
comment
Неправильно. В IE заголовки без кеширования игнорируются для вызовов XMLHttpRequest, как обсуждается здесь: stackoverflow.com/questions/244918/ DateTime (или мой метод .ajaxSetup) - единственные решения, которые действительно работают. - person Peter J; 30.01.2010
comment
я только что вставил свою обычную мантру без кеширования, не указано, что это специфично для IE - person miceuz; 01.02.2010
comment
Это должно отключить кеширование для всех браузеров: response.setHeader (Cache-Control, max-age = 0, no-cache, no-store, post-check = 0, pre-check = 0); - person Chris Broski; 15.04.2015

Лично я считаю, что метод строки запроса более надежен, чем попытка установить заголовки на сервере - нет гарантии, что прокси или браузер все равно не кэшируют его (некоторые браузеры хуже других - не называют имен).

Обычно я использую Math.random(), но я не вижу ничего плохого в использовании даты (не следует выполнять запросы AJAX достаточно быстро, чтобы дважды получить одно и то же значение).

person Greg    schedule 15.12.2008
comment
Объедините Date (). GetTime () вместе с Math.random (), и вы должны быть в безопасности. Кстати, Ext.Ajax также использует getTime (), если указано disableCaching. - person vividos; 15.12.2008

Следуя документации: http://api.jquery.com/jquery.ajax/

вы можете использовать свойство cache с:

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

Конечно, методы "взлома кеша" выполнят свою работу, но этого не произойдет в первую очередь, если сервер укажет клиенту, что ответ не должен кэшироваться. В некоторых случаях полезно кэшировать ответы, иногда нет. Пусть сервер определяет правильный срок жизни данных. Возможно, вы захотите изменить его позже. Гораздо проще сделать с сервера, чем из множества разных мест кода пользовательского интерфейса.

Конечно, это не поможет, если у вас нет контроля над сервером.

person Mark Renouf    schedule 15.12.2008

Настоящий вопрос в том, зачем вам это нужно, чтобы это не кешировалось. Если он не должен кэшироваться, потому что он все время изменяется, сервер должен указать, чтобы ресурс не кэшировался. Если он просто иногда меняется (потому что один из ресурсов, от которого он зависит, может измениться), и если у клиентского кода есть способ узнать об этом, он может добавить фиктивный параметр к URL-адресу, который вычисляется из некоторого хэша или даты последнего изменения этих ресурсов (это то, что мы делаем в ресурсах сценария Microsoft Ajax, чтобы их можно было кэшировать навсегда, но новые версии по-прежнему могут обслуживаться по мере их появления). Если клиент не может знать об изменениях, сервер должен правильно обрабатывать запросы HEAD и сообщать клиенту, использовать ли кешированную версию или нет. Мне кажется, что добавление случайного параметра или указание клиента никогда не кешировать неправильно, потому что кешируемость - это свойство серверного ресурса, и поэтому его следует решать на стороне сервера. Еще один вопрос, который следует задать себе: действительно ли этот ресурс должен обслуживаться через GET или он должен проходить через POST? Это вопрос семантики, но он также имеет последствия для безопасности (есть атаки, которые работают только в том случае, если сервер разрешает GET). POST не будет кэшироваться.

person Community    schedule 20.04.2009
comment
Что делать, если вы используете прокси-серверы, политику кэширования которых вы не контролируете? что, если вашему приложению явно нужно каждый раз выполнять новый запрос? Ответ на вопросы не всегда однозначный, черный и белый, всегда есть серые области. - person 7wp; 31.03.2011
comment
Правда, не всегда однозначно. Но, увидев этот ответ, я усомнился в своих предположениях и помог найти первопричину моей проблемы. Возможно, это не для всех, но мне это помогло. Если вы здесь и читаете это, вам также следует об этом подумать. - person Jonathan Tran; 17.08.2016
comment
Это мне помогло, ResponseCaching по умолчанию был настроен на 60-метровую сторону сервера. Изменил его на No-Cache, и он перестал кэшировать на клиенте. - person mattygee; 17.03.2020

Возможно, вам стоит вместо этого взглянуть на $ .ajax () (если вы используете jQuery, как это выглядит). Взгляните на: http://docs.jquery.com/Ajax/jQuery.ajax#options и вариант "кеш".

Другой подход - посмотреть, как вы кешируете вещи на стороне сервера.

person finpingvin    schedule 15.12.2008
comment
К сожалению, после некоторого расследования использование $ .ajax () и установка cache = false в основном будет делать то же самое. jQuery добавит случайное число в строку запроса и не проверяет существующую строку запроса. Поэтому я думаю, что будет достаточно использовать $ .get (). - person Salamander2007; 15.12.2008
comment
А, ладно. Никогда не пробовал, просто вспомнил, что видел кое-что об этом в документации :) - person finpingvin; 15.12.2008
comment
Даже не обязательно использовать $ .ajax. Просто используйте .ajaxSetup. - person Peter J; 09.04.2009

Как насчет использования запроса POST вместо GET ...? (Что вы должны в любом случае ...)

person Thomas Hansen    schedule 15.12.2008
comment
Я думаю, что это лучшее решение, но, к сожалению, я (как-то) могу выполнить только запрос GET. Итак .. это new Date (). GetTime () на данный момент. - person Salamander2007; 16.12.2008
comment
Пожалуйста, добавьте пояснение к своему ответу, чтобы другие могли извлечь из него уроки - зачем нужен POST-запрос? - person Nico Haase; 30.04.2020

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

Установка для кеширования значения false будет правильно работать только с запросами HEAD и GET. Он работает путем добавления "_ = {timestamp}" к параметрам GET. Параметр не требуется для других типов запросов, за исключением IE8, когда POST выполняется для URL-адреса, который уже был запрошен GET.

Так что установка только этого параметра не поможет вам в случае, о котором я упоминал выше.

person Athasach    schedule 06.05.2013

Небольшое дополнение к приведенным отличным ответам: если вы используете решение для резервного копирования, отличное от ajax, для пользователей без javascript, вам все равно придется исправить эти заголовки на стороне сервера. Это не невозможно, хотя я понимаю тех, кто откажется от этого;)

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

person krosenvold    schedule 15.12.2008

По сути, просто добавьте cache:false; в ajax, где, по вашему мнению, содержимое будет меняться по мере продвижения. И место, где контент не изменится, вы можете пропустить это. Таким образом вы будете получать новый ответ каждый раз

person Santosh Upadhayay    schedule 22.01.2014

Кэширование Ajax в Internet Explorer: что вы собираетесь с этим делать? предлагает три подхода:

  1. Добавьте токен очистки кеша в строку запроса, например? Date = [timestamp]. В jQuery и YUI вы можете указать им делать это автоматически.
  2. Используйте POST вместо GET
  3. Отправьте заголовок ответа HTTP, который специально запрещает браузерам кэшировать его
person LCJ    schedule 13.08.2014

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

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

Конечно, это не сработает для URL-адресов служб, которые не принадлежат вашему проекту. В этом случае вы можете рассмотреть возможность проксирования сторонней службы из серверного кода, а не ее вызова из клиентского кода.

person rstackhouse    schedule 01.08.2013

Теперь это легко сделать, включив / отключив опцию кеширования в вашем запросе 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);
    }
});
person El Don    schedule 24.11.2015
comment
Через 6 лет вы даете такой же ответ, что и Джонатан? ಠ_ಠ - person redent84; 26.02.2016
comment
люди могут сказать, что это через 6 лет после публикации вопроса. И мой ответ на этот вопрос отличается от любого другого, не говоря уже о том, что в настоящее время он правильный. Отвечать на такие вопросы - не для того, кто задает вопрос, а для сообщества и новичков! В любом случае спасибо за добавление разъяснений! - person El Don; 27.02.2016
comment
И в чем разница между вашим и этим stackoverflow.com/a/735084/469218? - person redent84; 28.02.2016
comment
может это ясность, с точки зрения новичка, задающего такой вопрос !! - person El Don; 28.02.2016

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

[OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
person Marius    schedule 16.05.2015
comment
Вы можете объяснить это дальше? Как этот массив связан с AJAX? - person Nico Haase; 30.04.2020
comment
Это не массив, это атрибут в действии контроллера MVC. - person Marius; 02.05.2020

Если вы используете IE 9, вам необходимо использовать следующее перед определением класса контроллера:

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

открытый класс TestController: Контроллер

Это предотвратит кеширование браузера.

Подробности по этой ссылке: http://dougwilsonsa.wordpress.com/2011/04/29/disables-ie9-ajax-response-caching-asp-net-mvc-3-jquery/

На самом деле это решило мою проблему.

person Net Solver    schedule 02.12.2012

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

headers: {
                'Cache-Control':'no-cache'
            }
person Moaz Salem    schedule 03.12.2019
comment
Пожалуйста, добавьте пояснения к своему ответу, чтобы другие могли извлечь из него уроки - где следует добавлять такие заголовки? - person Nico Haase; 30.04.2020

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

person xiaoyifang    schedule 03.12.2013
comment
Это даст нестабильные результаты. - person aj.toulan; 09.04.2014
comment
Math.random будет действовать только как праметр, например url? _ = [Math.Random ()], он не имеет ничего общего с нестабильным результатом. - person xiaoyifang; 10.04.2014
comment
Я понимаю, что вы делали. Я просто комментировал, что Math.Random () иногда дает вам одно и то же число дважды. Если вы заполните свою систему неопределенностями, они будут только дополнять друг друга. - person aj.toulan; 10.04.2014