Предотвращение кэширования браузером результата вызова jQuery AJAX

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

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

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

20 ответов


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

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

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


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

$.ajaxSetup({ cache: false });

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

$.get("myurl", myCallback)

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

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

другой способ-не предоставлять заголовки кэша из serverside в коде, который генерирует ответ на вызов 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'
   }
});

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

Я обычно использую 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, чтобы они может быть кэширован навсегда, но новые версии все еще могут быть поданы по мере их появления). Если клиент не может знать об изменениях, сервер должен правильно обрабатывать запросы HEAD и указывать клиенту, использовать ли кэшированную версию или нет. Мне кажется, что добавление случайного параметра или указание от клиента никогда не кэшировать неправильно, потому что кэшируемость является свойством ресурса сервера, и поэтому должно быть решено на стороне сервера. Еще один вопрос, который нужно задать себе: должен ли этот ресурс действительно обслуживаться через GET или он должен пройти через POST? Это вопрос семантики, но также имеет последствия для безопасности (есть атаки, которые работают только если сервер позволяет сделать). Сообщение не будет кэшироваться.


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

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


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

конечно это не поможет если тебя нет контроль над сервером.


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


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

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


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

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

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


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


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

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

теперь это легко сделать, включив / отключив опцию кэша в вашем запросе 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);
    }
});

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

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

открытый класс TestController: Controller

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

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

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


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

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

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


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


дописывать математику.random() на запрос url