Verhindern Sie das Browser-Caching des AJAX-Aufrufergebnisses

262

Wenn ich dynamische Inhalte mit lade $.get(), wird das Ergebnis im Browser zwischengespeichert.

Das Hinzufügen einer zufälligen Zeichenfolge in QueryString scheint dieses Problem zu lösen (ich verwende es new Date().toString()), aber dies fühlt sich wie ein Hack an.

Gibt es einen anderen Weg, um dies zu erreichen? Oder, wenn nur eine eindeutige Zeichenfolge dies erreichen kann, andere Vorschläge als new Date()?

Salamander2007
quelle
Sie können die Kurznotation verwenden, $.now()anstatt jedes Mal ein (neues Datum (). GetTime ()) auszuführen.
Dayson
1
Ihr Fragentitel ist ein bisschen irreführend. Könnten Sie darüber nachdenken, es umzubenennen?
0112
4
Haben Sie darüber nachgedacht, eine andere Antwort als die akzeptierte auszuwählen?
M4N

Antworten:

241

Ich verwende new Date().getTime(), um Kollisionen zu vermeiden, es sei denn, Sie haben mehrere Anfragen innerhalb derselben Millisekunde:

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

Bearbeiten: Diese Antwort ist mehrere Jahre alt. Es funktioniert immer noch (daher habe ich es nicht gelöscht), aber es gibt bessere / sauberere Möglichkeiten, dies jetzt zu erreichen . Ich bevorzuge diese Methode, aber diese Antwort ist auch nützlich, wenn Sie das Caching für jede Anforderung während der Lebensdauer einer Seite deaktivieren möchten .

Mark Bell
quelle
11
Ich werde nur abstimmen, weil es sauberer ist, jQuery dies tun zu lassen, wie in der Antwort von Peter J. Ihre Lösung wird funktionieren, ist aber auf lange Sicht schwieriger zu warten.
Niklas Wulff
11
Welcher Teil davon erfordert Wartung? Im Vergleich zu jQuery?
Sunny R Gupta
5
Es kann erwähnenswert sein , dass der new Date().getTime()Code wie folgt verwendet wird ... var nocache = new Date().getTime(); var path = 'http://hostname.domain.tld/api/somejsonapi/?cache=' + nocache;. Ich habe ein paar Minuten gebraucht, um das selbst herauszufinden. Natürlich ?cachekönnte jeder Wortlaut sein, den die API eigentlich nicht will.
doubleJ
1
+1 Auch Peter Js Antwort hat einen besseren Ansatz. Diese Antwort ist weder falsch noch eine schlechte Antwort. Ich glaube, dass die DV gemacht werden, weil deine über Peters liegt (wie akzeptiert). und das OP erscheint seit Anfang 2013 nicht mehr auf SO
Michel Ayres
1
url = url + (-1 === url.indexOf('?') ? '?' : '&') + "__=" + Number(new Date());
513

Im Folgenden wird verhindert, dass alle zukünftigen AJAX-Anforderungen zwischengespeichert werden, unabhängig davon, welche jQuery-Methode Sie verwenden ($ .get, $ .ajax usw.).

$.ajaxSetup({ cache: false });
Peter J.
quelle
7
Nach einer Untersuchung (Fiddler) sieht es so aus, als würde jQuery dies intern implementieren, indem ohnehin einfach ein Zeitstempel angehängt wird (wie an anderer Stelle in diesen Antworten erläutert). Für mich ist die .ajaxSetup-Methode sauberer (meiner Meinung nach)
Peter J
8
In der Tat muss es nicht innerhalb des dokumentenfertigen Aufrufs sein.
Peter J
19
Warum sollte das Ajax-Caching global deaktiviert werden? Ich denke, es sollte auf Anrufbasis erfolgen, so wie es Jonathans Antwort tut.
Sunny R Gupta
5
Was auch immer für Ihre App funktioniert. Ich verwende diese Methode weiterhin in kommerziellen Apps, wenn ich für alle AJAX-Anrufe unbedingt frische Daten benötige. Für andere sind zwischengespeicherte Daten in Ordnung.
Peter J
1
Link Beschreibung: Legen Sie Standardwerte für zukünftige Ajax-Anforderungen fest. Die Verwendung wird nicht empfohlen.
itwebdeveloper
319

JQuerys $ .get () speichert die Ergebnisse zwischen. Anstatt

$.get("myurl", myCallback)

Sie sollten $ .ajax verwenden, damit Sie das Caching deaktivieren können:

$.ajax({url: "myurl", success: myCallback, cache: false});
Jonathan Moffatt
quelle
62
+1 Dies ist die richtige Antwort. Peter Js Lösung, das Caching global zu deaktivieren, ist IMO eine schlechte Praxis.
Salman von Abbas
7
Es ist wichtig zu beachten, dass es nur "global" für die Seite / Anfrage ist.
Peter J
3
+1: Das Caching sollte spezifisch für den Anforderungstyp sein. Einige Serveranforderungen müssen möglicherweise zwischengespeichert werden (wenn die Serverdaten statisch sind). Daher ist es besser , das Zwischenspeichern auf Anforderung für Anforderung auszuwählen, als nur alles auszuschalten .
Gone Coding
1
+1 für die richtige Antwort - Verhindert das Zwischenspeichern pro Anruf mithilfe der jQuery-Methode und nicht anhand eines manuellen Hacks.
Brendan Hill
2
Eine weitere gute Antwort. Ich muss sagen, dass die globale Deaktivierung des Caches für mich die meiste Zeit von großem Vorteil war. Es hängt jedoch alles davon ab, wie Ihre Anwendung gestaltet ist. Es gibt keine Silberkugel, aber in dieser Situation würde ich eine Funktion empfehlen, die einen Booleschen Wert für das Caching, eine Funktion für den Rückruf und eine URL für die Modularität akzeptiert. Der manuelle "Hack" ist in Ordnung, aber wenn Sie jQuery verwenden, halten Sie sich nach Möglichkeit an deren Funktionen. Dies erleichtert nicht nur die Entwicklung jetzt, sondern auch zukünftige Upgrades der Bibliothek.
Anthony Mason
24

Alle Antworten hier hinterlassen einen Fußabdruck auf der angeforderten URL, der in den Zugriffsprotokollen des Servers angezeigt wird.

Ich brauchte eine Header-basierte Lösung ohne Nebenwirkungen und stellte fest, dass dies durch das Einrichten der unter So steuern Sie das Zwischenspeichern von Webseiten in allen Browsern genannten Header erreicht werden kann . .

Das Ergebnis, zumindest für Chrome, wäre:

$.ajax({
   url: url, 
   headers: {
     'Cache-Control': 'no-cache, no-store, must-revalidate', 
     'Pragma': 'no-cache', 
     'Expires': '0'
   }
});

Hilfe bei der
quelle
Vielleicht eine dumme Frage, aber wenn mein Ajax Bilder zurückgibt, werden die Bilder zwischengespeichert? Um massive Amazon S3-Anfragen zu vermeiden?
Marcelo Agimóvel
MarceloAgimóvel, das kann eine separate SO-Frage sein, glaube ich.
Aidin
23

Eine andere Möglichkeit besteht darin, im Code, der die Antwort auf einen Ajax-Aufruf generiert, keine Cache-Header von der Serverseite bereitzustellen:

response.setHeader( "Pragma", "no-cache" );
response.setHeader( "Cache-Control", "no-cache" );
response.setDateHeader( "Expires", 0 );
Mäuse
quelle
17
Falsch. Im IE werden die No-Cache-Header für XMLHttpRequest-Aufrufe ignoriert, wie hier erläutert : stackoverflow.com/questions/244918/… Die DateTime (oder meine .ajaxSetup-Methode) sind die einzigen Lösungen, die tatsächlich funktionieren.
Peter J
Ich habe gerade mein übliches Mantra ohne Cache eingefügt. Es wird nicht angegeben, dass es IE-spezifisch ist
Mäuse
2
Dies sollte das Caching für alle Browser beenden: response.setHeader ("Cache-Control", "maximales Alter = 0, kein Cache, kein Speicher, Nachprüfung = 0, Vorprüfung = 0");
Chris Broski
13

Persönlich bin ich der Meinung, dass die Abfragezeichenfolgenmethode zuverlässiger ist als der Versuch, Header auf dem Server festzulegen. Es gibt keine Garantie dafür, dass ein Proxy oder Browser sie ohnehin nicht einfach zwischenspeichert (einige Browser sind schlechter als andere - sie nennen keine Namen).

Normalerweise verwende Math.random()ich, aber ich sehe nichts falsches daran, das Datum zu verwenden (Sie sollten AJAX-Anfragen nicht schnell genug ausführen, um zweimal denselben Wert zu erhalten).

Greg
quelle
2
Kombinieren Sie Date (). GetTime () mit Math.random () und Sie sollten auf der sicheren Seite sein. Nebenbei bemerkt verwendet Ext.Ajax auch getTime (), wenn disableCaching angegeben ist.
Vividos
12

Befolgen Sie die Dokumentation: http://api.jquery.com/jquery.ajax/

Sie können die cacheEigenschaft verwenden mit:

$.ajax({
    method: "GET",
    url: "/Home/AddProduct?",
    data: { param1: value1, param2: value2},
    cache: false,
    success: function (result) {
        // TODO
    }
});
MrMins
quelle
5

Natürlich werden "Cache-Breaking" -Techniken die Arbeit erledigen, aber dies würde nicht in erster Linie passieren, wenn der Server dem Client anzeigt, dass die Antwort nicht zwischengespeichert werden soll. In einigen Fällen ist es vorteilhaft, Antworten zwischenzuspeichern, manchmal nicht. Lassen Sie den Server die richtige Lebensdauer der Daten bestimmen. Möglicherweise möchten Sie es später ändern. Vom Server aus viel einfacher als von vielen verschiedenen Stellen in Ihrem UI-Code.

Dies hilft natürlich nicht, wenn Sie keine Kontrolle über den Server haben.

Mark Renouf
quelle
5

Was ist mit einer POST-Anfrage anstelle eines GET ...? (Was du sowieso solltest ...)

Thomas Hansen
quelle
Ich denke, das ist eine bessere Lösung, aber leider kann ich (irgendwie) nur GET-Anfragen stellen. Also ... es ist neues Date (). GetTime () für jetzt.
Salamander2007
Bitte fügen Sie Ihrer Antwort eine Erklärung hinzu, damit andere daraus lernen können - warum sollte eine POST-Anfrage erforderlich sein?
Nico Haase
5

Die eigentliche Frage ist, warum Sie dies benötigen, um nicht zwischengespeichert zu werden. Wenn es nicht zwischengespeichert werden soll, weil es sich ständig ändert, sollte der Server angeben, dass die Ressource nicht zwischengespeichert werden soll. Wenn es sich nur manchmal ändert (weil sich eine der Ressourcen, von denen es abhängt, ändern kann) und der Client-Code eine Möglichkeit hat, dies zu wissen, kann er einen Dummy-Parameter an die URL anhängen, die aus einem Hash oder einem Datum der letzten Änderung berechnet wird dieser Ressourcen (das tun wir in Microsoft Ajax-Skriptressourcen, damit sie für immer zwischengespeichert werden können, aber neue Versionen können weiterhin so bereitgestellt werden, wie sie angezeigt werden). Wenn der Client keine Änderungen kennt, sollte der Server die HEAD-Anforderungen ordnungsgemäß verarbeiten und dem Client mitteilen, ob die zwischengespeicherte Version verwendet werden soll oder nicht. Mir scheint, dass das Anhängen eines zufälligen Parameters oder die Anweisung des Clients, niemals zwischenzuspeichern, falsch ist, da die Zwischenspeicherbarkeit eine Eigenschaft der Serverressource ist und daher serverseitig entschieden werden sollte. Eine andere Frage, die Sie sich stellen sollten, ist, ob diese Ressource wirklich über GET bereitgestellt werden soll oder ob sie über POST bereitgestellt werden soll. Das ist eine Frage der Semantik, hat aber auch Auswirkungen auf die Sicherheit (es gibt Angriffe, die nur funktionieren, wenn der Server GET zulässt). POST wird nicht zwischengespeichert.


quelle
6
Was ist, wenn Sie Proxyserver durchlaufen, deren Caching-Richtlinie Sie nicht kontrollieren? Was ist, wenn Ihre App jedes Mal explizit eine neue Anfrage stellen muss? Die Antwort auf die Dinge ist nicht immer eindeutig schwarz und weiß, es gibt immer graue Bereiche.
7wp
Es stimmt, es ist nicht immer eindeutig. Aber als ich diese Antwort sah, stellte ich meine Annahmen in Frage und fand die Grundursache für mein Problem. Das ist vielleicht nicht bei allen so, aber es hat mir geholfen. Wenn Sie dies hier lesen, sollten Sie es auch berücksichtigen.
Jonathan Tran
Dies hat mir geholfen. ResponseCaching war standardmäßig auf 60 m Server eingestellt. Es wurde in "Kein Cache" geändert und das Caching auf dem Client wurde gestoppt.
Mattygee
4

Vielleicht sollten Sie sich stattdessen $ .ajax () ansehen (wenn Sie jQuery verwenden, wie es aussieht). Schauen Sie sich Folgendes an: http://docs.jquery.com/Ajax/jQuery.ajax#options und die Option "Cache".

Ein anderer Ansatz wäre, zu untersuchen, wie Sie Dinge auf der Serverseite zwischenspeichern.

Finpingvin
quelle
1
Leider wird nach einigen Nachforschungen die Verwendung von $ .ajax () und das Setzen von cache = false im Grunde dasselbe bewirken. jQuery fügt dem Querystring eine Zufallszahl hinzu und sucht nicht nach vorhandenem Querystring. Ich denke also, dass die Verwendung von $ .get () ausreichen wird.
Salamander2007
Ah Okey. Ich habe es nie ausprobiert, habe mich nur daran erinnert, dass ich in den Dokumenten etwas darüber gesehen habe :)
finpingvin
Es ist nicht einmal notwendig, $ .ajax zu verwenden. Verwenden Sie einfach .ajaxSetup.
Peter J
3

Eine kleine Ergänzung zu den hervorragenden Antworten: Wenn Sie mit einer Nicht-Ajax-Sicherungslösung für Benutzer ohne Javascript arbeiten, müssen Sie diese serverseitigen Header trotzdem korrekt einstellen. Das ist nicht unmöglich, obwohl ich diejenigen verstehe, die es aufgeben;)

Ich bin sicher, es gibt noch eine andere Frage zu SO, die Ihnen den vollständigen Satz geeigneter Header liefert. Ich bin nicht ganz überzeugt, dass die Antwort von Mäusen alle Basen zu 100% abdeckt.

Krosenvold
quelle
3

Für diejenigen unter Ihnen, die die cacheOption für $.ajaxSetup()mobile Safari verwenden, scheint es, dass Sie möglicherweise einen Zeitstempel für POSTs verwenden müssen, da Mobile Safari dies auch zwischenspeichert. Gemäß der Dokumentation zu $.ajax()(auf die Sie verwiesen werden $.ajaxSetup()):

Das Setzen des Caches auf false funktioniert nur bei HEAD- und GET-Anforderungen ordnungsgemäß. Es funktioniert, indem "_ = {Zeitstempel}" an die GET-Parameter angehängt wird. Der Parameter wird für andere Arten von Anforderungen nicht benötigt, außer in IE8, wenn ein POST an eine URL gesendet wird, die bereits von einem GET angefordert wurde.

Wenn Sie diese Option allein einstellen, hilft Ihnen dies in dem oben genannten Fall nicht weiter.

Athasach
quelle
2

Fügen Sie einfach cache:false;den Ajax hinzu, in dem sich der Inhalt im Laufe der Zeit ändern wird. Und der Ort, an dem sich der Inhalt dort nicht ändert, kann man weglassen. Auf diese Weise erhalten Sie jedes Mal die neue Antwort

Santosh Upadhayay
quelle
2

Ajax-Caching im Internet Explorer: Was werden Sie dagegen tun? schlägt drei Ansätze vor:

  1. Fügen Sie der Abfragezeichenfolge ein Cache-Busting-Token hinzu, z. B.? Date = [timestamp]. In jQuery und YUI können Sie sie anweisen, dies automatisch zu tun.
  2. Verwenden Sie POST anstelle von GET
  3. Senden Sie einen HTTP-Antwortheader, der es Browsern ausdrücklich verbietet, ihn zwischenzuspeichern
LCJ
quelle
2

Jetzt ist es einfach, die Cache-Option in Ihrer Ajax-Anfrage zu aktivieren / deaktivieren

$(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);
    }
});
Omar El Don
quelle
3
Nach 6 Jahren geben Sie die gleiche Antwort wie Jonathan? ಠ_ಠ
redent84
Leute können sagen, dass es 6 Jahre nach dem Posten der Frage ist. Und meine Antwort auf diese Frage unterscheidet sich von jeder anderen, ganz zu schweigen davon, dass sie heutzutage richtig ist. Die Beantwortung solcher Fragen ist nicht für den "Fragesteller", sondern für die Community und Anfänger! Vielen Dank für die Klarstellung!
Omar El Don
Und was ist der Unterschied zwischen Ihrem und diesem einen stackoverflow.com/a/735084/469218 ?
redent84
Vielleicht ist es Klarheit aus der Sicht eines Anfängers, der eine solche Frage stellt !!
Omar El Don
1

Wie @Athasach sagte, funktioniert es laut den jQuery-Dokumenten $.ajaxSetup({cache:false})nur für GET- und HEAD-Anforderungen.

Sie sind Cache-Control: no-cachesowieso besser dran, einen Header von Ihrem Server zurückzusenden. Es bietet eine sauberere Trennung von Bedenken.

Dies würde natürlich nicht für Service-URLs funktionieren, die nicht zu Ihrem Projekt gehören. In diesem Fall können Sie in Betracht ziehen, den Dienst eines Drittanbieters über den Servercode zu übertragen, anstatt ihn über den Clientcode aufzurufen.

rstackhouse
quelle
1

Wenn Sie .net ASP MVC verwenden, deaktivieren Sie das Caching für die Controller-Aktion, indem Sie der Endpunktfunktion das folgende Attribut hinzufügen:

[OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
Marius
quelle
Können Sie das weiter erklären? In welcher Beziehung steht dieses Array zu AJAX?
Nico Haase
Es ist kein Array, sondern ein Attribut für eine MVC-Controller-Aktion.
Marius
0

Header hinzufügen

headers: {
                'Cache-Control':'no-cache'
            }
Moaz Salem
quelle
Bitte fügen Sie Ihrer Antwort eine Erklärung hinzu, damit andere daraus lernen können - wo sollten solche Überschriften hinzugefügt werden?
Nico Haase
-3

Math.random() an die Anforderungs-URL anhängen

Xiaoyifang
quelle
2
Dies führt zu instabilen Ergebnissen.
Aj.toulan
Math.random fungiert nur als Parameter, wie url? _ = [Math.Random ()], es hat nichts mit instabilem Ergebnis zu tun.
Xiaoyifang
4
Ich verstehe, was du getan hast. Ich habe nur kommentiert, dass Math.Random () Ihnen manchmal zweimal dieselbe Nummer gibt. Wenn Sie Ihr System mit Unsicherheiten füllen, werden diese nur übereinander addiert.
Aj.toulan