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

StackOverflow https://stackoverflow.com/questions/367786

Вопрос

Это выглядит так, как если бы я загружал динамический контент с помощью $.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 });

Функция $.get() jQuery будет кэшировать результаты.Вместо того, чтобы

$.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'
   }
});

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

Обычно я использую 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
    }
});

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

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

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

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

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

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

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

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

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

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

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

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

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

  1. Добавьте токен перебора кэша в строку запроса, например ?date=[временная метка].В 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 :Контроллер

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

Подробности по этой ссылке: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(переменный параметр = "*", Длительность = 0, NoStore = true)]

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top