Похоже, если я загружаю динамический контент с помощью $.get()
, результат кэшируется в браузере.
Добавление некоторой случайной строки в QueryString, похоже, решает эту проблему (я использую new Date().toString()
), но это похоже на взлома.
Есть ли другой способ достичь этого?
Или, если уникальная строка является единственным способом достижения этого, любые предложения, кроме new Date()
?
Я использую new Date().getTime()
, который избежит коллизий, если у вас не будет несколько запросов в течение одной миллисекунды:
$.get('/getdata?_=' + new Date().getTime(), function(data) {
console.log(data);
});
Изменить: Этот ответ несколько лет. Он по-прежнему работает (следовательно, я его не удалял), но есть лучшие/более чистые способы достижения этого сейчас. Я предпочитаю этот метод, но этот ответ также полезен, если вы хотите отключить кеширование для каждого запроса во время жизни страницы.
Следующее предотвратит кеширование всех будущих запросов AJAX, независимо от того, какой метод jQuery вы используете ($.get, $.ajax и т.д.)
$.ajaxSetup({ cache: false });
JQuery $.get() будет кэшировать результаты. Вместо
$.get("myurl", myCallback)
вам следует использовать $.ajax, который позволит вам отключить кеширование:
$.ajax({url: "myurl", success: myCallback, cache: false});
другой способ - не предоставлять заголовки кеша с сервера в коде, который генерирует ответ на вызов ajax:
response.setHeader( "Pragma", "no-cache" );
response.setHeader( "Cache-Control", "no-cache" );
response.setDateHeader( "Expires", 0 );
Все ответы здесь оставляют след на запрошенном URL-адресе, который будет отображаться в журналах доступа к серверу.
Мне понадобилось решение на основе заголовка без побочного эффекта, и я нашел, что его можно достичь, настроив заголовки, упомянутые в Как управлять кэшированием веб-страниц во всех браузерах?.
Результаты, работающие, по крайней мере, для Chrome, будут
$.ajax({
url: url,
headers: {
'Cache-Control': 'no-cache, no-store, must-revalidate',
'Pragma': 'no-cache',
'Expires': '0'
}
});
Вы можете использовать короткую нотацию $.now()
вместо выполнения (new Date(). getTime()) каждый раз.
Лично я считаю, что метод строки запроса более надежный, чем попытка установить заголовки на сервере - нет гарантии, что прокси-сервер или браузер не будут кэшировать его в любом случае (некоторые браузеры хуже других, не называя имен).
Я обычно использую Math.random()
, но я не вижу ничего плохого в использовании даты (вы не должны делать запросы AJAX достаточно быстро, чтобы получить одно и то же значение дважды).
Следуя документации: http://api.jquery.com/jquery.ajax/
вы можете использовать свойство cache
с помощью:
$.ajax({
method: "GET",
url: "/Home/AddProduct?",
data: { param1: value1, param2: value2},
cache: false,
success: function (result) {
// TODO
}
});
Реальный вопрос в том, почему вам это нужно, чтобы не кэшироваться. Если он не должен кэшироваться, потому что он все время меняется, сервер должен указать, чтобы не кэшировать ресурс. Если он просто изменяется иногда (поскольку один из ресурсов, от которого он зависит, может измениться), и если код клиента имеет способ узнать об этом, он может добавить фиктивный параметр к URL-адресу, который вычисляется из некоторого хэша или последней измененной даты (что мы делаем в ресурсах Microsoft Ajax script, чтобы их можно было кэшировать навсегда, но новые версии все равно могут обслуживаться по мере их появления). Если клиент не знает об изменениях, правильный путь должен быть для сервера правильно обрабатывать HEAD-запросы и сообщать клиенту, следует ли использовать кешированную версию или нет. Мне кажется, что добавление случайного параметра или сообщение от клиента никогда не кэшируются неправильно, потому что кеширование является свойством ресурса сервера, поэтому его следует решать на стороне сервера. Другой вопрос, чтобы спросить себя, должен ли этот ресурс действительно обслуживаться через ПОЛУЧИТЬ или должен ли он проходить через POST? Это вопрос семантики, но также имеет последствия для безопасности (есть атаки, которые работают, только если сервер разрешает GET). POST не будет кэшироваться.
Конечно, методы "кэширования" будут выполняться, но это не произойдет в первую очередь, если сервер указал клиенту, что ответ не должен быть кэширован. В некоторых случаях полезно кэшировать ответы, иногда нет. Пусть сервер решит правильное время жизни данных. Возможно, вы захотите изменить его позже. Гораздо проще сделать с сервера, чем из разных мест вашего кода пользовательского интерфейса.
Конечно, это не поможет, если у вас нет контроля над сервером.
Как насчет использования запроса POST вместо GET...? (Что вам все равно нужно...)
Для тех из вас, кто использует опцию cache
для $.ajaxSetup()
на мобильном Safari, кажется, вам, возможно, придется использовать временную метку для POST, так как кэш Safari также кэширует это. Согласно документации на $.ajax()
(к которой вы перенаправлены с $.ajaxSetup()
):
Установка кеша в false будет работать только с запросами HEAD и GET. Он работает, добавляя "_ = {timestamp}" к параметрам GET. Параметр не нужен для других типов запросов, за исключением IE8, когда POST создается с URL-адресом, который уже был запрошен GET.
Поэтому настройка этого параметра сама по себе не поможет вам в случае, о котором я упоминал выше.
Небольшое дополнение к отличным ответам: если вы работаете с решением для резервного копирования без аякса для пользователей без javascript, вам все равно нужно будет получить эти заголовки на стороне сервера. Это не невозможно, хотя я понимаю тех, кто его отказывается;)
Я уверен, что есть еще один вопрос о SO, который даст вам полный набор заголовков, которые подходят. Я не полностью уверен, что ответ miceus охватывает все базы на 100%.
Может быть, вам стоит посмотреть на $.ajax() вместо этого (если вы используете jQuery, как это выглядит). Взгляните на: http://docs.jquery.com/Ajax/jQuery.ajax#options и опцию "cache".
Другим подходом было бы посмотреть, как вы кешируете вещи на стороне сервера.
Теперь легко сделать это, включив/отключив параметр кеша в своем аякс-запросе, точно так же, как этот
$(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);
}
});
Интернет-исследователи Ajax Caching: что вы собираетесь делать с этим? предлагает три подхода:
- Добавьте к строке запроса маркер перебора кеша, например: date = [timestamp]. В jQuery и YUI вы можете сказать им сделать это автоматически.
- Используйте POST вместо GET
- Отправлять заголовок ответа HTTP, который специально запрещает браузеру кэшировать его.
В основном просто добавьте cache:false;
в ajax, где, по вашему мнению, содержимое изменится по мере продвижения. И место, где контент не изменится, может упустить это. Таким образом, u будет получать новый ответ каждый раз
Как сказал @Athasach, согласно документам jQuery, $.ajaxSetup({cache:false})
не будет работать, кроме запросов GET и HEAD.
В любом случае вам лучше не отправлять заголовок Cache-Control: no-cache
со своего сервера. Это обеспечивает более четкое разделение проблем.
Конечно, это не сработает для служебных URL-адресов, которые вы не принадлежите вашему проекту. В этом случае вы можете подумать о проксинге службы сторонних поставщиков из кода сервера, а не называть его кодом клиента.
Если вы используете IE 9, вам нужно использовать следующее перед определением класса контроллера:
[OutputCache (NoStore = true, Duration = 0, VaryByParam = "*" )]
открытый класс TestController: контроллер
Это предотвратит кеширование браузера.
Подробная информация об этой ссылке: http://dougwilsonsa.wordpress.com/2011/04/29/disabling-ie9-ajax-response-caching-asp-net-mvc-3-jquery/
На самом деле это решило мою проблему.
Если вы используете .net ASP MVC, отключите кеширование действия контроллера, добавив в функцию конечной точки следующий атрибут: [OutputCacheAttribute (VaryByParam = "*", Duration = 0, NoStore = true)]
добавить Math.random() в URL запроса
$.now()
вместо выполнения (new Date (). GetTime ()) каждый раз.