Nieoczekiwane buforowanie AJAX skutkuje w IE8

135

Mam poważny problem z wynikami buforowania Internet Explorera z żądania JQuery Ajax.

Mam nagłówek na mojej stronie internetowej, który jest aktualizowany za każdym razem, gdy użytkownik przechodzi do nowej strony. Robię to po załadowaniu strony

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

Po prostu wstrzykuje informacje nagłówka na stronę. Możesz to sprawdzić, wchodząc na www.wikipediamaze.com, a następnie logując się i rozpoczynając nową łamigłówkę.

W każdej testowanej przeze mnie przeglądarce (Google Chrome, Firefox, Safari, Internet Explorer) działa świetnie poza IE. Wszystko zostaje dobrze wstrzyknięte w IE za pierwszym razem, ale potem już nigdy nie wykonuje wywołania /game/getpuzzleinfo. To tak, jakby zapisał wyniki w pamięci podręcznej lub coś takiego.

Jeśli zmienię połączenie na $.post("/game/getpuzzleinfo", ...IE, odbierze je dobrze. Ale potem Firefox przestaje działać.

Czy ktoś może rzucić trochę światła na to, dlaczego IE buforuje moje $.getwywołania Ajax?

AKTUALIZACJA

Zgodnie z poniższą sugestią zmieniłem moje żądanie Ajax na to, co rozwiązało mój problem:

$.ajax({
    type: "GET",
    url: "/game/getpuzzleinfo",
    dataType: "json",
    cache: false,
    success: function(data) { ... }
});
Micheasza
źródło
8
Dzięki za pytanie. Zaniemówiłem, że to zachowanie przeglądarki.
jjohn
1
Dobre pytanie i naprawdę fajna strona internetowa. Dobry pomysł.
MikeMurko

Odpowiedzi:

177

IE jest znany z agresywnego buforowania odpowiedzi Ajax. Ponieważ używasz jQuery, możesz ustawić opcję globalną:

$.ajaxSetup({
    cache: false
});

co spowoduje, że jQuery doda losową wartość do ciągu zapytania żądania, uniemożliwiając w ten sposób IE buforowanie odpowiedzi.

Zauważ, że jeśli masz inne wywołania Ajax w miejscu, w którym chcesz buforować, spowoduje to również wyłączenie go dla nich. W takim przypadku przełącz się na metodę $ .ajax () i włącz tę opcję jawnie dla niezbędnych żądań.

Więcej informacji można znaleźć pod adresem http://docs.jquery.com/Ajax/jQuery.ajaxSetup .

NickFitz
źródło
1
Możesz również dodać sygnaturę czasową na końcu swoich adresów URL. Nie jestem pewien, dlaczego jQuery nie stosuje tego podejścia.
Eric Johnson,
14
@Eric: to właśnie robi jQuery wewnętrznie - opcja "cache: false" po prostu nakazuje mu to zrobić.
NickFitz,
Dlaczego jquery nie ma tego domyślnie włączonego?
szybowiec
Właśnie zauważyłem, że opcje pamięci podręcznej nie działają, gdy próbujesz zażądać strony głównej w IE 8 za pomocą wywołania /. Zmień go na /index.phplub jakikolwiek inny pełny adres URL. Lub sam dodaj fałszywe parametry, takie jak/?f=f
Hugo Delsing,
8

Jak wspomniano w marr75 , plikiGET są buforowane.

Jest kilka sposobów, aby temu zaradzić. Oprócz modyfikowania nagłówka odpowiedzi można również dołączyć losowo wygenerowaną zmienną ciągu zapytania na koniec docelowego adresu URL. W ten sposób IE będzie myśleć, że jest to inny adres URL za każdym razem, gdy zostanie o to poproszony.

Można to zrobić na wiele sposobów (np. Przez użycie Math.random(), zmiana daty itp.).

Oto jeden sposób, w jaki możesz to zrobić:

var oDate = new Date();
var sURL = "/game/getpuzzleinfo?randomSeed=" + oDate.getMilliseconds();
$.get(sURL, null, function(data, status) {
    // your work
});
Tomek
źródło
3

Pobiera są zawsze buforowalne. Jedną ze strategii, która może zadziałać, jest edycja nagłówka odpowiedzi i poinformowanie klienta, aby nie buforował informacji lub aby wkrótce wygaśnął pamięć podręczną.

marr75
źródło
To brzmi jak dobry pomysł. Jak bym to zrobił?
Micah
1
To załadowane pytanie, zależy od kodu po stronie serwera. Zobacz wpis Wikipedii „Lista nagłówków HTTP”, aby uzyskać małe wskazówki. Przykłady: Cache-Control: no-cache Expires: Thu, 01 grudnia 1994 16:00:00 GMT Zasadniczo musisz dołączyć te nagłówki odpowiedzi do odpowiedzi http. Jest to dość proste w ASP.NET, Ruby i PHP. Po prostu wyszukaj język po stronie serwera, którego używasz + zmodyfikuj nagłówki odpowiedzi.
marr75
3
Ponadto, i to wcale nie jest krytyka Jquery (uwielbiam tę bibliotekę), metoda dodawania losowego parametru ciągu zapytania jest bezpieczna, ale niegrzeczna dla klienta (może pozostawić go trzymającego elementy w pamięci podręcznej, które nigdy nie będą używane jeszcze raz).
marr75
2

Jeśli wywołujesz stronę ashx, możesz również wyłączyć cache na serwerze za pomocą następującego kodu:

context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches); 
Andrej Benedik
źródło
1

oto co robię dla wywołań Ajax:

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

na mnie działa całkiem nieźle.

Jason
źródło
1

NickFitz daje dobrą odpowiedź, ale musisz też wyłączyć buforowanie w IE9. Aby kierować tylko na IE8 i IE9, możesz to zrobić;

<!--[if lte IE 9]>
<script>
    $.ajaxSetup({
        cache: false
    });
</script>
<![endif]-->
Stuart Hallows
źródło
0

Odpowiedzi tutaj są bardzo pomocne dla tych, którzy używają jQuery lub z jakiegoś powodu bezpośrednio używają obiektu xmlHttpRequest ...

Jeśli korzystasz z automatycznie generowanego serwera proxy usługi Microsoft, nie jest to tak proste do rozwiązania.

Sztuczka polega na użyciu metody Sys.Net.WebRequestManager.add_invokingRequest w obsłudze zdarzeń, aby zmienić adres URL żądania:

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

Pisałem o tym na blogu: http://yoavniran.wordpress.com/2010/04/27/ie-caching-ajax-results-how-to-fix/

poeticGeek
źródło
0

Właśnie napisałem bloga na ten temat, używając tylko ExtJS ( http://thecodeabode.blogspot.com/2010/10/cache-busting-ajax-requests-in-ie.html )

Problem polegał na tym, że korzystałem z określonego formatu przepisywania adresu URL i nie mogłem użyć konwencjonalnych parametrów ciągu zapytania (? Param = wartość), więc zamiast tego napisałem parametr usuwania pamięci podręcznej jako opublikowaną zmienną ..... pomyślałbym że używanie zmiennych POST jest nieco bezpieczniejsze niż GET, po prostu dlatego, że wiele frameworków MVC używa tego wzorca

protokół: // host / kontroler / akcja / param1 / param2

a więc mapowanie nazwy zmiennej do wartości jest tracone, a parametry są po prostu układane w stosy ... więc przy użyciu parametru do pomijania pamięci podręcznej GET

tj. protokół: // host / kontroler / akcja / param1 / param2 / no_cache122300201

no_cache122300201 można pomylić z parametrem $ param3, który może mieć wartość domyślną

to znaczy

akcja funkcji publicznej ($ param1, $ param2, $ param3 = "wartość domyślna") {//..//}

nie ma szans, aby tak się stało w przypadku POSTED busterów pamięci podręcznej

Ben
źródło
0

Jeśli korzystasz z ASP.NET MVC, wystarczy dodać ten wiersz na górze akcji kontrolera:

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

}
batmaci
źródło
To zachowanie występuje po stronie przeglądarki; ta odpowiedź dotyczy buforowania po stronie serwera.
Mark Sowul,
@MarkSowul Outputcache ma 3 opcje Klient, Serwer i dowolne. IE domyślnie używa OutputCache, który działa głównie jako buforowanie po stronie klienta. Możesz zobaczyć więcej szczegółów tutaj dougwilsonsa.wordpress.com/2011/04/29/…
batmaci
@MarkSowul możesz również zobaczyć powiązane pytanie i odpowiedź tutaj. Czy myślisz, że jest to również po stronie serwera? stackoverflow.com/questions/2653092/…
batmaci
1
Tak, przepraszam, masz rację - nie zdawałem sobie sprawy, że twoja odpowiedź może wpłynąć zarówno na pamięć podręczną po stronie serwera, jak i pamięć podręczną po stronie klienta.
Mark Sowul
-1

IE ma prawo do tego buforowania; aby upewnić się, że element nie jest buforowany, nagłówki powinny być odpowiednio ustawione.

Jeśli używasz ASP.NET MVC, możesz napisać ActionFilter; w OnResultExecuted, sprawdź filterContext.HttpContext.Request.IsAjaxRequest(). Jeśli tak, ustaw nagłówek expire odpowiedzi:filterContext.HttpContext.Response.Expires = -1;

Zgodnie z http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/ :

Niektórzy wolą używać nagłówka Cache - Control: no - cache zamiast expires. Oto różnica:
Cache-Control: no-cache - absolutnie BEZ buforowania
Wygasa: -1 - przeglądarka „zwykle” kontaktuje się z serwerem WWW w celu aktualizacji tej strony za pośrednictwem warunkowego żądania If-Modified-Since. Jednak strona pozostaje w pamięci podręcznej dysku i jest używana w odpowiednich sytuacjach bez kontaktowania się ze zdalnym serwerem WWW, na przykład gdy przyciski WSTECZ i DO PRZODU służą do uzyskiwania dostępu do historii nawigacji lub gdy przeglądarka jest w trybie offline.

Mark Sowul
źródło