1101 Stimmen

Legt Safari unter iOS 6 $.ajax-Ergebnisse zwischen?

Seit dem Upgrade auf iOS 6 nimmt sich die Webansicht von Safari die Freiheit, zwischenzuspeichern $.ajax ruft. Dies geschieht im Kontext einer PhoneGap-Anwendung, die also die Safari WebView verwendet. Unser $.ajax Anrufe sind POST Methoden und wir haben den Cache auf false gesetzt {cache:false} aber das Problem tritt immer noch auf. Wir haben versucht, manuell eine TimeStamp zu den Kopfzeilen hinzugefügt, aber das hat nicht geholfen.

Wir haben weitere Nachforschungen angestellt und festgestellt, dass Safari nur bei Webdiensten mit einer statischen Funktionssignatur, die sich von Aufruf zu Aufruf nicht ändert, Ergebnisse aus dem Cache zurückgibt. Stellen Sie sich zum Beispiel eine Funktion vor, die etwa so heißt:

getNewRecordID(intRecordType)

Diese Funktion erhält immer wieder dieselben Eingabeparameter, aber die Daten, die sie zurückgibt, sollten jedes Mal anders sein.

In der Eile, mit der Apple iOS 6 zum Laufen bringen wollte, haben sie sich wohl zu sehr mit den Cache-Einstellungen begnügt. Hat noch jemand dieses Verhalten bei iOS 6 beobachtet? Wenn ja, was genau ist die Ursache?


Die Abhilfe, die wir gefunden haben, besteht darin, die Funktionssignatur so zu ändern, dass sie etwa so aussieht:

getNewRecordID(intRecordType, strTimestamp)

und geben Sie dann immer eine TimeStamp und verwerfen Sie diesen Wert einfach auf der Serverseite. Auf diese Weise lässt sich das Problem umgehen.

450voto

Kieran Punkte 5736

Nach ein wenig Nachforschung stellt sich heraus, dass Safari auf iOS6 POSTs zwischenspeichert, die entweder keine Cache-Control-Header oder sogar "Cache-Control: max-age=0" haben.

Die einzige Möglichkeit, die ich gefunden habe, um zu verhindern, dass diese Zwischenspeicherung auf globaler Ebene geschieht, anstatt zufällige Querystrings am Ende von Serviceaufrufen zu hacken, ist die Einstellung "Cache-Control: no-cache".

Also:

  • Keine Cache-Control- oder Expires-Header = iOS6 Safari zwischenspeichert
  • Cache-Control max-age=0 und ein sofortiges Expires = iOS6 Safari zwischenspeichert
  • Cache-Control: no-cache = iOS6 Safari wird NICHT zwischenspeichern

Ich vermute, dass Apple sich dies aus der HTTP-Spezifikation in Abschnitt 9.5 über POST zunutze macht:

Antworten auf diese Methode sind nicht zwischenspeicherbar entsprechende Cache-Control- oder Expires-Header-Felder enthält. Allerdings kann jedoch die Antwort 303 (siehe Sonstiges) verwendet werden, um den User-Agent anzuweisen eine cachefähige Ressource abzurufen.

Theoretisch können Sie also POST-Antworten zwischenspeichern... wer hätte das gedacht. Aber kein anderer Browserhersteller hat bis jetzt gedacht, dass das eine gute Idee wäre. Aber das gilt NICHT für das Caching, wenn keine Cache-Control- oder Expires-Header gesetzt sind, sondern nur, wenn welche gesetzt sind. Es muss also ein Fehler sein.

Unten steht, was ich im rechten Teil meiner Apache-Konfiguration verwende, um die gesamte API zu erreichen, da ich eigentlich nichts zwischenspeichern möchte, nicht einmal gets. Was ich nicht weiß, ist, wie man dies nur für POSTs setzen.

Header set Cache-Control "no-cache"

Update: Mir ist gerade aufgefallen, dass ich nicht darauf hingewiesen habe, dass es nur dann der Fall ist, wenn die POST-Daten gleich sind, d.h. wenn man die POST-Daten oder die URL ändert, ist alles in Ordnung. So können Sie, wie an anderer Stelle erwähnt, fügen Sie einfach einige zufällige Daten auf die URL oder ein bisschen von POST-Daten.

Update: Sie können den "no-cache" nur auf POSTs beschränken, wenn Sie dies im Apache so wünschen:

SetEnvIf Request_Method "POST" IS_POST
Header set Cache-Control "no-cache" env=IS_POST

149voto

Dave Punkte 1511

Ich hoffe, dies kann anderen Entwicklern, die mit dem Kopf gegen die Wand rennen, von Nutzen sein. Ich habe festgestellt, dass einer der folgenden Punkte Safari unter iOS 6 daran hindert, die POST-Antwort zwischenzuspeichern:

  • Hinzufügen von [cache-control: no-cache] in die Kopfzeilen der Anfrage
  • Hinzufügen eines variablen URL-Parameters, z. B. der aktuellen Uhrzeit
  • Hinzufügen von [pragma: no-cache] in die Antwort-Header
  • Hinzufügen von [cache-control: no-cache] in den Antwort-Headern

Meine Lösung war die folgende in meinem Javascript (alle meine AJAX-Anfragen sind POST).

$.ajaxSetup({
    type: 'POST',
    headers: { "cache-control": "no-cache" }
});

Ich füge auch die Kopfzeile [pragma: no-cache] zu vielen meiner Serverantworten hinzu.

Wenn Sie die obige Lösung verwenden, sollten Sie sich bewusst sein, dass alle $.ajax()-Aufrufe, die auf global: false gesetzt sind, NICHT die in $.ajaxSetup() angegebenen Einstellungen verwenden, so dass Sie die Header erneut hinzufügen müssen.

70voto

Baz1nga Punkte 15240

Einfache Lösung für alle Ihre Web-Service-Anfragen, vorausgesetzt, Sie verwenden jQuery:

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
    // you can use originalOptions.type || options.type to restrict specific type of requests
    options.data = jQuery.param($.extend(originalOptions.data||{}, { 
      timeStamp: new Date().getTime()
    }));
});

Lesen Sie mehr über den jQuery-Vorfilteraufruf aquí .

Wenn Sie nicht jQuery verwenden, lesen Sie die Dokumentation der Bibliothek Ihrer Wahl. Sie haben möglicherweise ähnliche Funktionen.

45voto

Bashevis Punkte 1479

Ich hatte dieses Problem auch gerade in einer PhoneGap Anwendung. Ich habe das Problem mit Hilfe der JavaScript-Funktion getTime() auf folgende Weise:

var currentTime = new Date();
var n = currentTime.getTime();
postUrl = "http://www.example.com/test.php?nocache="+n;
$.post(postUrl, callbackFunction);

Ich habe ein paar Stunden damit verschwendet, das herauszufinden. Es wäre nett von Apple gewesen, die Entwickler über dieses Caching-Problem zu informieren.

43voto

Tadej Punkte 429

Ich hatte das gleiche Problem mit einer Webapp, die Daten von einem ASP.NET-Webservice abruft

Das hat bei mir funktioniert:

public WebService()
{
    HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    ...
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X