2008-12-15 3 views
217

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

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

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

+1

Ваш вопрос название является немного вводит в заблуждение. Можно ли переименовать его? – 0112 2014-07-17 15:56:10

+4

Рассматривали ли вы выбор другого ответа как принятого? – M4N 2015-07-22 13:31:01

ответ

204

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

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

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

+11

Я буду использовать только потому, что я могу позволить jQuery сделать это, как в ответе Питера Дж. Ваше решение будет работать, но в долгосрочной перспективе его сложнее поддерживать. – 2011-01-13 12:46:58

+10

Какая часть этого требует обслуживания? По сравнению с тем, что делает jQuery? – 2013-05-30 09:02:16

+5

Возможно, стоит отметить, что код `new Date(). GetTime() используется так:` var nocache = new Date(). GetTime(); var path = 'http: //hostname.domain.tld/api/somejsonapi/? cache =' + nocache; `. Мне потребовалось несколько минут, чтобы понять это. Конечно, `? Cache` может быть любой формулировкой, которую API действительно не хочет. – doubleJ 2013-07-10 04:15:34

18

другой путь, чтобы не вызывать кэш заголовки из ServerSide в коде, который генерирует ответ на Ajax вызова:

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

Неверный. В IE заголовки no-cache игнорируются для вызовов XMLHttpRequest, как описано здесь: http://stackoverflow.com/questions/244918/internet-explorer-7-ajax-links-only-load-once DateTime (или мой.ajaxSetup) - единственные решения, которые действительно работают. – 2010-01-29 22:35:39

+0

Я только что приклеил свою обычную кеш-мантру, не указано, что это специфичный IE – miceuz 2010-02-01 11:46:49

+1

Это должно отключить кеширование для всех браузеров: response.setHeader («Cache-Control», «max-age = 0, no- кэш, нет-магазин, после проверки = 0, предварительно проверка = 0"); – 2015-04-15 17:22:08

13

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

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

+2

Комбинировать дату(). GetTime() вместе с Math.random(), и вы должны быть в безопасности. На стороне примечание, Ext.Ajax также использует getTime(), когда указано disableCaching. – vividos 2008-12-15 09:53:08

3

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

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

+1

К сожалению, после некоторого исследования использование $ .ajax() и set cache = false в основном будет делать то же самое. jQuery добавит случайное число в строку запроса и не проверяет существующие запросы. Поэтому я предполагаю, что использование $ .get() будет достаточным. – Salamander2007 2008-12-15 09:33:15

+0

Ah okey. Никогда не пробовал, просто вспомнил, что видел что-то об этом в документах :) – finpingvin 2008-12-15 09:59:28

+0

Нет даже смысла использовать $ .ajax. Просто используйте .ajaxSetup. – 2009-04-09 17:12:25

3

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

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

4

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

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

4

Как насчет использования запроса POST вместо GET ...? (Который вам все равно ...)

267

JQuery's $ .get() будет кэшировать результаты. Вместо

$.get("myurl", myCallback) 

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

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

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

$.ajaxSetup({ cache: false }); 
6

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

13

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

1

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

[OutputCache (NoStore = True, Продолжительность = 0, VaryByParam = "*")]

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

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

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

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

3

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

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

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

1

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

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

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

2

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

2

Internet Explorer’s Ajax Caching: What Are YOU Going To Do About It? предлагает три подхода:

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

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

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

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

Если вы используют .net ASP MVC, отключить кэширование на действие контроллера, добавив следующий атрибут функции конечной точки: [OutputCacheAttribute (VaryByParam = "*", Продолжительность = 0, NoStore = истина)]

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); 
    } 
}); 
12

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

Мне нужно решение на основе заголовка без побочного эффекта, и я нашел, что его можно достичь, установив заголовки, упомянутые в How to control web page caching, across all browsers?.

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

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