Неожиданное кэширование результатов AJAX в IE8


135

У меня серьезная проблема с результатами кэширования Internet Explorer из запроса JQuery Ajax.

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

$.get("/game/getpuzzleinfo", null, function(data, status) {
    var content = "<h1>Wikipedia Maze</h1>";
    content += "<p class='endtopic'>Looking for <span><a title='Opens the topic you are looking for in a separate tab or window' href='" + data.EndTopicUrl + "' target='_blank'>" + data.EndTopic + "<a/></span></p>";
    content += "<p class='step'>Step <span>" + data.StepCount + "</span></p>";
    content += "<p class='level'>Level <span>" + data.PuzzleLevel.toString() + "</span></p>";
    content += "<p class='startover'><a href='/game/start/" + data.PuzzleId.toString() + "'>Start Over</a></p>";

    $("#wikiheader").append(content);

}, "json");

Он просто вводит информацию заголовка на страницу. Вы можете проверить это, зайдя на www.wikipediamaze.com, а затем войдя в систему и запустив новую головоломку.

В каждом браузере, который я тестировал (Google Chrome, Firefox, Safari, Internet Explorer), он отлично работает, кроме IE. Eveything впрыскивается очень хорошо в IE в первый раз, но после этого он даже не звонит /game/getpuzzleinfo. Это как если бы он кешировал результаты или что-то в этом роде.

Если я изменяю вызов на $.post("/game/getpuzzleinfo", ...IE, то поднимает трубку. Но тогда Firefox перестает работать.

Может кто-нибудь, пожалуйста, пролить свет на то, почему IE кеширует мои $.getajax-вызовы?

ОБНОВИТЬ

Согласно приведенному ниже предложению, я изменил свой запрос ajax на это, что решило мою проблему:

$.ajax({
    type: "GET",
    url: "/game/getpuzzleinfo",
    dataType: "json",
    cache: false,
    success: function(data) { ... }
});

8
Спасибо за вопрос. Я потерял дар речи, что это поведение браузера.
jjohn

1
Хороший вопрос и действительно классный сайт. Отличная идея.
MikeMurko

Ответы:


177

IE известен своим агрессивным кэшированием ответов Ajax. Поскольку вы используете jQuery, вы можете установить глобальную опцию:

$.ajaxSetup({
    cache: false
});

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

Обратите внимание, что если у вас есть другие Ajax-вызовы, где вы хотите кэшировать, это отключит его и для них. В этом случае переключитесь на использование метода $ .ajax () и включите эту опцию явно для необходимых запросов.

См. Http://docs.jquery.com/Ajax/jQuery.ajaxSetup для получения дополнительной информации.


1
Вы также можете добавить отметку времени в конце ваших URL. Не уверен, почему jQuery не использует этот подход.
Эрик Джонсон

14
@Eric: это то, что делает jQuery внутри - опция «cache: false» просто говорит ему сделать это.
NickFitz

Почему jquery не имеет этого по умолчанию?
скоростной самолет

Я только что заметил, что параметры кэширования не работают, когда вы пытаетесь запросить домашнюю страницу в IE 8 с вызовом /. Измените его на /index.phpкакой-либо полный URL-адрес. Или добавить некоторые поддельные Params себя как/?f=f
Hugo Delsing

8

Как упоминалось в marr75 ,GET кешируются.

Есть несколько способов борьбы с этим. Помимо изменения заголовка ответа, вы также можете добавить случайно сгенерированную переменную строки запроса в конец целевого URL. Таким образом, IE будет думать, что это новый URL каждый раз, когда его запрашивают.

Есть несколько способов сделать это (например, используя Math.random() , изменение даты и т. Д.).

Вот один из способов сделать это:

var oDate = new Date();
var sURL = "/game/getpuzzleinfo?randomSeed=" + oDate.getMilliseconds();
$.get(sURL, null, function(data, status) {
    // your work
});

3

Получает всегда кешируется. Одна из стратегий, которая может сработать, - это отредактировать заголовок ответа и сказать клиенту, чтобы он не кэшировал информацию или очень скоро истек срок действия кэша.


Это звучит как хорошая идея. Как бы я поступил так?
Мика

1
Это загруженный вопрос, зависит от вашего кода на стороне сервера. Посмотрите запись в Википедии "Список заголовков HTTP" для небольшого руководства. Примеры: Cache-Control: no-cache Срок действия истекает: четверг, 01 декабря 1994 16:00:00 GMT Обычно вам нужно добавить эти заголовки ответа в ваш http-ответ. Это довольно просто в ASP.NET, Ruby и PHP. Просто найдите язык на стороне сервера, который вы используете + измените заголовки ответа.
marr75

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

2

Если вы вызываете страницу Ashx, вы также можете отключить кэширование на сервере с помощью следующего кода:

context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches); 

1

это то, что я делаю для вызовов ajax:

var url = "/mypage.aspx";
// my other vars i want to add go here
url = url + "&sid=" + Math.random();
// make ajax call

это работает довольно хорошо для меня.


1

NickFitz дает хороший ответ, но вам нужно отключить кеширование и в IE9. Чтобы нацелиться только на IE8 и IE9, вы можете сделать это;

<!--[if lte IE 9]>
<script>
    $.ajaxSetup({
        cache: false
    });
</script>
<![endif]-->

0

Ответы здесь очень полезны для тех, кто использует jQuery или по какой-то причине напрямую использует объект xmlHttpRequest ...

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

Хитрость заключается в том, чтобы использовать метод Sys.Net.WebRequestManager.add_invokingRequest в обработчике событий, чтобы изменить URL запроса:

networkRequestEventArgs._webRequest._url = networkRequestEventArgs._webRequest._url + '&nocache=' + new Date().getMilliseconds(); 

Я написал в блоге об этом: http://yoavniran.wordpress.com/2010/04/27/ie-caching-ajax-results-how-to-fix/


0

Только что написал блог по этому вопросу только с использованием ExtJS ( http://thecodeabode.blogspot.com/2010/10/cache-busting-ajax-requests-in-ie.html )

Проблема заключалась в том, что, когда я использовал определенный формат переписывания URL-адресов, я не мог использовать обычные параметры строки запроса (? Param = value), поэтому вместо этого мне пришлось написать параметр очистки кэша ..... я бы подумал что использование переменных POST немного безопаснее, чем GET, просто потому, что многие MVC-фреймворки используют шаблон

протокол: // хост / контроллер / действие / param1 / param2

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

т.е. протокол: // хост / контроллер / действие / param1 / param2 / no_cache122300201

no_cache122300201 можно принять за параметр $ param3, который может иметь значение по умолчанию

т.е.

действие публичной функции ($ param1, $ param2, $ param3 = "значение по умолчанию") {//..//}

никаких шансов на то, что это случится с кешами POSTED


0

Если вы используете ASP.NET MVC, достаточно добавить эту строку поверх действия контроллера:

[OutputCache(NoStore=true, Duration = 0, VaryByParam = "None")]
public ActionResult getSomething()
{

}

Поведение в вопросе на стороне браузера; Этот ответ относится к кешированию на стороне сервера.
Марк Соул

@MarkSowul Outputcache имеет 3 варианта клиента, сервера и любой. IE использует OutputCache по умолчанию любой, который идет в основном как кэширование на стороне клиента. Вы можете увидеть более подробную информацию здесь dougwilsonsa.wordpress.com/2011/04/29/…
batmaci

@MarkSowul вы также можете увидеть соответствующий вопрос и ответ здесь. Как вы думаете, это также на стороне сервера? stackoverflow.com/questions/2653092/…
batmaci

1
Да, извините, вы правы - я не осознавал, что ваш ответ может повлиять как на кэш на стороне сервера, так и на кэш на стороне клиента.
Марк Соул

-1

IE имеет право делать это кеширование; чтобы гарантировать, что элемент не кэшируется, заголовки должны быть установлены соответственно.

Если вы используете ASP.NET MVC, вы можете написать ActionFilter; в OnResultExecuted, проверитьfilterContext.HttpContext.Request.IsAjaxRequest() . Если это так, установите заголовок expire ответа:filterContext.HttpContext.Response.Expires = -1;

Согласно http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/ :

Некоторые люди предпочитают использовать заголовок Cache - Control: no - cache вместо срока действия. Вот в чем разница:
Cache-Control: no-cache - абсолютно NO кеширование
Истекает: -1 - браузер «обычно» связывается с веб-сервером для обновления этой страницы с помощью условного запроса If-Modified-Since. Однако страница остается в дисковом кеше и используется в соответствующих ситуациях без обращения к удаленному веб-серверу, например, когда кнопки BACK и FORWARD используются для доступа к истории навигации или когда браузер находится в автономном режиме.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.