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.

2voto

ShadeTreeDeveloper Punkte 1493

Ich war in der Lage, mein Problem zu beheben, indem Sie eine Kombination von $.ajaxSetup und Anhängen eines Zeitstempels an die Url meines Beitrags (nicht auf die Post-Parameter / Körper). Dies basiert auf den Empfehlungen der vorherigen Antworten

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

    $('#myForm').submit(function() {
        var data = $('#myForm').serialize();
        var now = new Date();
        var n = now.getTime();
        $.ajax({
            type: 'POST',
            url: 'myendpoint.cfc?method=login&time='+n,
            data: data,
            success: function(results){
                if(results.success) {
                    window.location = 'app.cfm';
                } else {
                    console.log(results);
                    alert('login failed');
                }
            }
        });
    });
});

2voto

Ivo Jansch Punkte 1358

Das Hinzufügen von Cache-Buster-Parametern, um die Anfrage anders aussehen zu lassen, scheint zwar eine solide Lösung zu sein, aber ich würde davon abraten, da es jeder Anwendung schaden würde, die auf tatsächliches Caching angewiesen ist. Die APIs dazu zu bringen, die richtigen Header auszugeben, ist die bestmögliche Lösung, auch wenn das etwas schwieriger ist als das Hinzufügen von Cache-Bustern zu den Aufrufern.

1voto

cbmeeks Punkte 10978

Für diejenigen, die Struts 1 Ich habe das Problem folgendermaßen gelöst.

web.xml

<filter>
    <filter-name>SetCacheControl</filter-name>
    <filter-class>com.example.struts.filters.CacheControlFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>SetCacheControl</filter-name>
    <url-pattern>*.do</url-pattern>
    <http-method>POST</http-method>
</filter-mapping>

com.example.struts.filters.CacheControlFilter.js

package com.example.struts.filters;

import java.io.IOException;
import java.util.Date;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;

public class CacheControlFilter implements Filter {

        public void doFilter(ServletRequest request, ServletResponse response,
                     FilterChain chain) throws IOException, ServletException {

        HttpServletResponse resp = (HttpServletResponse) response;
        resp.setHeader("Expires", "Mon, 18 Jun 1973 18:00:00 GMT");
        resp.setHeader("Last-Modified", new Date().toString());
        resp.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0");
        resp.setHeader("Pragma", "no-cache");

        chain.doFilter(request, response);
    }

    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void destroy() {
    }

}

1voto

Lanello Punkte 59

Ich denke, Sie haben Ihr Problem bereits gelöst, aber lassen Sie mich eine Idee über Web-Caching teilen.

Sie können zwar in jeder Sprache, die Sie verwenden, viele Header hinzufügen, serverseitig, clientseitig, und Sie können viele andere Tricks anwenden, um Web-Caching zu vermeiden, aber denken Sie immer daran, dass Sie nie wissen können, von wo aus sich der Client mit Ihrem Server verbindet, Sie wissen nie, ob er eine Hotel-"Hot-Spot"-Verbindung verwendet, die Squid oder andere Caching-Produkte nutzt.

Wenn der Benutzer einen Proxy verwendet, um seine tatsächliche Position zu verbergen, usw., wird die real Die einzige Möglichkeit, die Zwischenspeicherung zu vermeiden, ist der Zeitstempel in der Anfrage, auch wenn er nicht verwendet wird.

Zum Beispiel:

/ajax_helper.php?ts=3211321456

Jeder Cache-Manager, den Sie passieren müssen, findet dann nicht dieselbe URL im Cache-Repository und lädt den Seiteninhalt erneut herunter.

1voto

CaptureWiz Punkte 1473

Wir haben festgestellt, dass ältere iPhones und iPads, auf denen die iOS-Versionen 9 und 10 laufen, gelegentlich falsche, leere AJAX-Ergebnisse zurückliefern, was vielleicht darauf zurückzuführen ist, dass Apple die CPU-Geschwindigkeit reduziert hat. Wenn das leere Ergebnis zurückgegeben wird, ruft iOS den Server nicht auf, als ob ein Ergebnis aus dem Cache zurückgegeben würde. Die Häufigkeit ist sehr unterschiedlich und liegt zwischen etwa 10 % und 30 % der AJAX-Aufrufe, die ein leeres Ergebnis zurückgeben.

Die Lösung ist kaum zu glauben. Einfach 1s warten und erneut anrufen. In unseren Tests war nur eine Wiederholung nötig, aber wir haben den Code so geschrieben, dass er bis zu vier Mal aufgerufen werden kann. Wir sind uns nicht sicher, ob die Wartezeit von 1s erforderlich ist, aber wir wollten nicht riskieren, unseren Server mit einer Flut von wiederholten Aufrufen zu belasten.

Wir haben festgestellt, dass das Problem bei zwei verschiedenen AJAX-Aufrufen auftrat, die unterschiedliche API-Dateien mit unterschiedlichen Daten aufriefen. Aber ich bin besorgt, dass es bei jedem AJAX-Aufruf passieren könnte. Wir wissen es einfach nicht, weil wir nicht jedes AJAX-Ergebnis überprüfen und nicht jeden Aufruf mehrfach auf alten Geräten testen.

Beide problematischen AJAX-Aufrufe wurden verwendet: POST, Asynchronous = true, setRequestHeader = ('Content-Type', 'application/x-www-form-urlencoded')

Wenn das Problem auftritt, gibt es normalerweise nur einen AJAX-Aufruf. Es liegt also nicht an sich überschneidenden AJAX-Aufrufen. Manchmal tritt das Problem auf, wenn das Gerät beschäftigt ist, manchmal aber auch nicht, und ohne DevTools wissen wir nicht wirklich, was zu diesem Zeitpunkt passiert.

Bei iOS 13 ist das nicht der Fall, auch nicht bei Chrome oder Firefox. Wir haben keine Testgeräte, auf denen iOS 11 oder 12 läuft. Vielleicht kann jemand anderes diese testen?

Ich vermerke dies hier, weil diese Frage bei der Suche nach diesem Problem bei Google an erster Stelle steht.

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