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

225

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

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

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

  • 0
    Вы можете использовать короткую запись $.now() вместо выполнения (new Date (). GetTime ()) каждый раз.
  • 1
    Название вашего вопроса немного вводит в заблуждение. Можете ли вы переименовать его?
Показать ещё 1 комментарий
Теги:
browser-cache

21 ответ

207
Лучший ответ

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

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

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

  • 11
    Я буду опускать голоса только потому, что позволить jQuery делать это чище, как в ответе Питера Дж. Ваше решение будет работать, но его будет труднее поддерживать в долгосрочной перспективе.
  • 11
    Какая часть этого требует обслуживания? По сравнению с тем, что делает JQuery?
Показать ещё 4 комментария
461

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

$.ajaxSetup({ cache: false });
  • 5
    После расследования (Fiddler), похоже, что jQuery реализует это внутренне, просто добавив временную метку в любом случае (как обсуждалось в других местах этих ответов). Для меня метод .ajaxSetup чище (на мой взгляд.)
  • 0
    Красиво и чисто - отлично! :-)
Показать ещё 15 комментариев
277

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

$.get("myurl", myCallback)

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

$.ajax({url: "myurl", success: myCallback, cache: false});
  • 56
    +1 Это правильный ответ. Решение Питера J о глобальном отключении кэширования является плохой практикой IMO.
  • 6
    Важно отметить, что это только «глобальный» для страницы / запроса.
Показать ещё 5 комментариев
19

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

response.setHeader( "Pragma", "no-cache" );
response.setHeader( "Cache-Control", "no-cache" );
response.setDateHeader( "Expires", 0 );
  • 17
    Неправильно. В IE заголовки без кэширования игнорируются для вызовов XMLHttpRequest, как обсуждено здесь: stackoverflow.com/questions/244918/… DateTime (или мой метод .ajaxSetup) - единственные решения, которые действительно работают.
  • 0
    я только что вставил свою обычную не кэш-мантру, не указано, что это специфично для IE
Показать ещё 1 комментарий
14

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

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

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

$.ajax({
   url: url, 
   headers: {
     'Cache-Control': 'no-cache, no-store, must-revalidate', 
     'Pragma': 'no-cache', 
     'Expires': '0'
   }
});
  • 1
    Спасибо :) ..............
  • 0
    Возможно глупый вопрос, но если мой ajax вернет изображения, будут ли изображения кэшироваться? Чтобы избежать массивных запросов Amazon S3?
13

Вы можете использовать короткую нотацию $.now() вместо выполнения (new Date(). getTime()) каждый раз.

13

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

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

  • 2
    Объедините Date (). GetTime () вместе с Math.random (), и вы должны быть в безопасности. В дополнение к этому, Ext.Ajax также использует getTime (), когда указано disableCaching.
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
    }
});
5

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

  • 5
    Что делать, если вы используете прокси-серверы, которые не контролируют их политику кэширования? Что если вашему приложению явно нужно каждый раз делать новый запрос? Ответом на вещи не всегда является четкое черно-белое изображение, всегда присутствуют серые участки.
  • 0
    Правда, это не всегда ясно. Но, увидев этот ответ, я усомнился в своих предположениях и нашел причину своей проблемы. Это может быть не для всех, но это помогло мне. Если вы здесь читаете это, вы должны рассмотреть это также.
4

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

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

4

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

  • 0
    Я думаю, что это лучшее решение, но, к сожалению, я (как-то) могу только сделать запрос GET. Так что .. теперь это новый Date (). GetTime ().
3

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

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

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

3

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

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

3

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

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

  • 1
    К сожалению, после некоторого исследования использование $ .ajax () и set cache = false в основном сделает то же самое. jQuery добавит случайное число в строку запроса и не проверяет существующую строку запроса. Поэтому я думаю, что использования $ .get () будет достаточно.
  • 0
    Ах, ладно. Никогда не пробовал, просто вспомнил, что видел что-то об этом в документации :)
Показать ещё 1 комментарий
2

Теперь легко сделать это, включив/отключив параметр кеша в своем аякс-запросе, точно так же, как этот

$(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);
    }
});
  • 2
    Через 6 лет вы отвечаете так же, как Джонатан? ಠ_ಠ
  • 0
    люди могут сказать, что прошло 6 лет после того, как вопрос опубликован. И мой ответ на этот вопрос отличается от любого другого, не говоря уже о том, что в настоящее время он правильный. Отвечать на такие вопросы не для «спрашивающего», а для сообщества и начинающих! Спасибо за добавление разъяснения в любом случае!
Показать ещё 2 комментария
2

Интернет-исследователи Ajax Caching: что вы собираетесь делать с этим? предлагает три подхода:

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

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

1

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

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

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

1

Если вы используете 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/

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

0

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

-4

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

  • 1
    Это даст нестабильные результаты.
  • 0
    Math.random будет действовать только как параметр, например url? _ = [Math.Random ()], он не имеет ничего общего с нестабильным результатом.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню