Safari su iOS 6 memorizza nella cache i risultati $ .ajax?


1072

Dall'aggiornamento a iOS 6, vediamo la vista Web di Safari prendere la libertà di effettuare $.ajaxchiamate nella cache . Questo è nel contesto di un'applicazione PhoneGap, quindi utilizza Safari WebView. Le nostre $.ajaxchiamate sono POSTmetodi e la cache è impostata su false {cache:false}, ma continua a succedere. Abbiamo provato ad aggiungere manualmente un TimeStampalle intestazioni ma non ha aiutato.

Abbiamo fatto ulteriori ricerche e abbiamo scoperto che Safari sta solo restituendo risultati memorizzati nella cache per i servizi Web che hanno una firma di funzione che è statica e non cambia da chiamata a chiamata. Ad esempio, immagina una funzione chiamata qualcosa del tipo:

getNewRecordID(intRecordType)

Questa funzione riceve ripetutamente gli stessi parametri di input, ma i dati che restituisce dovrebbero essere sempre diversi.

Deve essere nella fretta di Apple per rendere iOS 6 zip in modo impressionante e sono diventati troppo contenti delle impostazioni della cache. Qualcun altro ha visto questo comportamento su iOS 6? In tal caso, cosa lo sta causando esattamente?


La soluzione alternativa che abbiamo trovato è stata quella di modificare la firma della funzione in modo che fosse simile a questa:

getNewRecordID(intRecordType, strTimestamp)

quindi passa sempre anche un TimeStampparametro e scarta quel valore sul lato server. Questo risolve il problema. Spero che questo aiuti qualche altra povera anima che trascorre 15 ore su questo problema come ho fatto io!


190
Questo è assolutamente scioccante. Abbiamo anche trascorso un paio d'ore cercando di capire cosa ha smesso di funzionare. Il nostro login AJAX che esegue un POST (e ha intestazioni per impedire anche la memorizzazione nella cache) viene memorizzato nella cache da Safari, quindi restituisce lo stesso JSON che ha fatto l'ultima volta senza nemmeno provare il server ... incredibile! Dovremo hackerare una correzione, ma non dovresti mai mettere in cache un POST, è pazzesco.
Kieran

16
Pubblica la tua soluzione come risposta anziché come aggiornamento alla domanda.
ChrisF

50
Le richieste POST sono non idempotenti, il che significa che non devono essere memorizzate nella cache a meno che la risposta non lo consenta espressamente tramite le intestazioni di risposta.
James M. Greene,

6
Per far sì che Apple risolva questo problema, invia un bug su bugreport.apple.com . Ho fatto lo stesso.
Mathias Bynens,

11
Mark Nottingham (presidente del gruppo di lavoro IETF HTTPbis) ha scritto oggi un interessante post su questo blog: mnot.net/blog/2012/09/24/caching_POST
Benjamin Brizzi

Risposte:


447

Dopo un po 'di indagine, si scopre che Safari su iOS6 memorizzerà nella cache i POST che non hanno intestazioni Cache-Control o addirittura "Cache-Control: max-age = 0".

L'unico modo che ho trovato per impedire che questa memorizzazione nella cache si verificasse a livello globale piuttosto che dover hackerare querystring casuali sulle chiamate di fine servizio è impostare "Cache-Control: no-cache".

Così:

  • Nessun controllo cache o scadenze = iOS6 Safari memorizzerà nella cache
  • Cache-Control max-age = 0 e una scadenza immediata = iOS6 Safari memorizzerà nella cache
  • Controllo cache: no-cache = iOS6 Safari NON memorizzerà nella cache

Sospetto che Apple stia approfittando di questo dalle specifiche HTTP nella sezione 9.5 su POST:

Le risposte a questo metodo non sono memorizzabili nella cache, a meno che la risposta non includa i campi di intestazione Controllo cache o Scadenza appropriati. Tuttavia, la risposta 303 (Vedi altro) può essere utilizzata per indirizzare l'agente utente a recuperare una risorsa memorizzabile nella cache.

Quindi in teoria puoi memorizzare nella cache le risposte POST ... chi lo sapeva. Ma nessun altro produttore di browser ha mai pensato che sarebbe stata una buona idea fino ad ora. Ma ciò NON tiene conto della memorizzazione nella cache quando non sono impostate intestazioni Cache-Control o Expires, solo quando sono presenti alcuni set. Quindi deve essere un bug.

Di seguito è quello che uso nel bit giusto della mia configurazione di Apache per indirizzare l'intera mia API perché, come succede, in realtà non voglio memorizzare nulla nella cache, nemmeno lo ottengo. Quello che non so è come impostare questo solo per i POST.

Header set Cache-Control "no-cache"

Aggiornamento: ho appena notato che non ho sottolineato che è solo quando il POST è lo stesso, quindi cambia uno qualsiasi dei dati POST o l'URL e stai bene. Quindi, come menzionato altrove, è sufficiente aggiungere alcuni dati casuali all'URL o un po 'di dati POST.

Aggiornamento: Puoi limitare il "no-cache" solo ai POST se lo desideri in Apache:

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

7
Vedo dove Apple sta andando con questo, ma stiamo vedendo le risposte memorizzate nella cache alle richieste POST anche quando le nostre risposte non includevano intestazioni Cache-Control o Expires. Questa istanza iOS6 non dovrebbe memorizzare nella cache e inviare ogni richiesta. Questo non sta succedendo.
Kango_V,

138
La parte delle specifiche HTTP che hai citato non giustifica il comportamento della cache di iOS 6. Il comportamento predefinito dovrebbe essere quello di non memorizzare nella cache le risposte POST (ovvero quando l'intestazione "Cache-Control" non è definita). Il comportamento viola le specifiche e deve essere considerato un bug. Chiunque costruisca servizi web xml / json api dovrebbe decorare le proprie risposte POST con "Cache-control: no-cache" per aggirare questo problema.
David H,

39
Le richieste POST sono non idempotenti, il che significa che non devono essere memorizzate nella cache a meno che la risposta non lo consenta espressamente tramite le intestazioni di risposta.
James M. Greene,

4
Come dice David, è una chiara violazione della frase che hai citato. Se non ci sono "campi di intestazione Cache-Control or Expires", ovviamente tali intestazioni non sono incluse. Eppure la tua indagine mostra che è cache in quello scenario. Modifica la tua risposta
Matthew Flaschen

3
Qualcuno sa per quanto tempo il risultato viene memorizzato nella cache su un dispositivo? Ho provato a uccidere Safari e riavviare il mio telefono, ma è ancora nella cache. So che funziona con la pulizia della cache del browser, ma mi chiedo quanto tempo ci vorrà per gli utenti che una volta hanno avuto il problema prima che scompaia. Non tutti penseranno di svuotare la cache ...
Daniel Hallqvist,

146

Spero che questo possa essere utile ad altri sviluppatori che sbattono la testa contro il muro su questo. Ho scoperto che uno dei seguenti impedisce a Safari su iOS 6 di memorizzare nella cache la risposta POST:

  • aggiungendo [cache-control: no-cache] nelle intestazioni della richiesta
  • aggiungendo un parametro URL variabile come l'ora corrente
  • aggiungendo [pragma: no-cache] nelle intestazioni di risposta
  • aggiungendo [cache-control: no-cache] nelle intestazioni di risposta

La mia soluzione era la seguente nel mio Javascript (tutte le mie richieste AJAX sono POST).

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

Aggiungo anche l'intestazione [pragma: no-cache] a molte delle risposte del mio server.

Se si utilizza la soluzione di cui sopra, tenere presente che le chiamate $ .ajax () effettuate sono globali: false NON utilizzerà le impostazioni specificate in $ .ajaxSetup (), quindi sarà necessario aggiungere nuovamente le intestazioni.


4
Questa è LA CORRETTA soluzione al bug. Il bug è che iOS 6 gestirà le richieste POST dalla sua cache invece di inviarle al server. Il bug non è che memorizza nella cache le risposte dalle richieste POST (che è consentito). Se si desidera ancora che le risposte alle richieste POST vengano recuperate dalla cache per le successive richieste GET a tale URI, utilizzare questa soluzione.
Nicholas Shanks,

2
Questo funziona per me, ma non capisco come. Avevo già specificato cache: false nel mio ajaxSetup, e guardando le intestazioni della richiesta, che si riduce a Cache-Control: no-cache e Pragma: no-cache - ma continuerà a memorizzare nella cache dell'iPad. Quindi quando aggiungo le intestazioni: {"cache-control": "no-cache"} in ajaxSetup, raddoppia l'intestazione Cache-Control in "no-cache, no-cache" - e interrompe la memorizzazione nella cache. Cosa sta succedendo qui?
Tom W Hall,

Funziona perfettamente - puoi anche aggiungere alla richiesta come parametro $ .ajax ({tipo: 'POST', intestazioni: {'cache-control': 'no-cache'}, ecc.})
George Filippakos

Che cos'è [pragma: no-cache]? A cosa serve la chiave pragma?
zakdances,

Penso anche che questo sia l'approccio migliore, piuttosto che una soluzione alternativa con un parametro aggiuntivo. Lo abbiamo aggiunto solo alle chiamate in cui ne avevamo bisogno, per le chiamate che hanno sempre lo stesso rendimento, la memorizzazione nella cache è probabilmente una buona cosa per l'utente finale.
germankiwi,

67

Soluzione semplice per tutte le tue richieste di servizi web, supponendo che stai utilizzando 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()
    }));
});

Maggiori informazioni sulla chiamata al prefiltro jQuery qui .

Se non stai usando jQuery, controlla i documenti per la tua libreria di scelta. Potrebbero avere funzionalità simili.


3
Per me non funziona, il server risponde: "JSON primitivo non valido: timestamp" asp.net / iis 7.5
Alexandre

3
che dire di $ .ajax ({"cache": false ...})? funzionerà come aggiungere un _ = [TIMESTAMP]? (Non possiedo un dispositivo del genere per testarlo)
Karussell,

Ho pubblicato un'implementazione completa della soluzione proposta da Karussell. Vedi la mia risposta qui sotto.
Sam Shiles,

1
@Karussell. Ho appena provato a impostare $ .ajax ({"cache": false ...}). Questo non risolve il problema per le richieste POST su iOS6. Presumibilmente perché JQuery secondo i loro documenti presume che nessun browser sia abbastanza stupido da memorizzare nella cache le richieste di post. "Le pagine recuperate con POST non vengono mai memorizzate nella cache, quindi la cache e le opzioni ifModified in jQuery.ajaxSetup () non hanno alcun effetto su queste richieste."
Brett Hannah,

1
Questo non funziona Non unisce i parametri post. Il post di Dave è una soluzione migliore.
Chris Muench,

43

Ho appena avuto questo problema anche in un'applicazione PhoneGap . L'ho risolto utilizzando la funzione JavaScript getTime()nel modo seguente:

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

Ho perso qualche ora a capirlo. Sarebbe stato carino per Apple informare gli sviluppatori di questo problema di memorizzazione nella cache.


1
Stavo per commentare l'uso {cache:false}come opzione per uno $.post()o $.ajaxSetup(), ma secondo i documenti , questi argomenti sono ignorati; jQuery "non memorizzerà mai nella cache" le richieste di post, ma non prende in considerazione il browser. Forse un'opzione migliore sarebbe quella di aggiungere un timestamp alle richieste usando $.ajaxPrefilter().
fwielstra,

spendo quasi 5 ore per risolvere questo problema e, infine, l'aggiunta di timestamp farà il trucco function send_ajax(my_data,refresh) .. fare riferimento qui
stackoverflow.com/questions/14733772/…

42

Ho avuto lo stesso problema con una webapp che otteneva dati dal servizio web ASP.NET

Questo ha funzionato per me:

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

2
Grazie mille! Stavo impazzendo cercando di capire perché l'iPhone si stava comportando in modo così diverso rispetto a qualsiasi altra piattaforma. Questa soluzione specifica ASP.NET mi ha fatto risparmiare un sacco di tempo.
Mark Brittingham,

Non ha funzionato su iOS6, vedi la mia risposta verso la fine del thread
Brian Ogden,

1
Per favore!!!! Metti una condizione per applicarlo solo su IOS 6, la cache dei contenuti è vitale per qualsiasi applicazione.
Alexandre,

24

Infine, ho una soluzione al mio problema di caricamento.

In JavaScript:

var xhr = new XMLHttpRequest();
xhr.open("post", 'uploader.php', true);
xhr.setRequestHeader("pragma", "no-cache");

In PHP :

header('cache-control: no-cache');

15

Dal mio post sul blog iOS 6.0 memorizza nella cache le richieste POST Ajax :

Come risolverlo: esistono vari metodi per impedire la memorizzazione nella cache delle richieste. Il metodo consigliato è l'aggiunta di un'intestazione senza cache. Ecco come si fa.

jQuery:

Verifica iOS 6.0 e imposta l'intestazione Ajax in questo modo:

$.ajaxSetup({ cache: false });

ZeptoJS:

Verifica iOS 6.0 e imposta l'intestazione Ajax in questo modo:

$.ajax({
    type: 'POST',
    headers : { "cache-control": "no-cache" },
    url : ,
    data:,
    dataType : 'json',
    success : function(responseText) {…}

Lato server

Giava:

httpResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");

Assicurati di aggiungere questo nella parte superiore della pagina prima di inviare i dati al client.

.NETTO

Response.Cache.SetNoStore();

O

Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);

PHP

header('Cache-Control: no-cache, no-store, must-revalidate'); // HTTP 1.1.
header('Pragma: no-cache'); // HTTP 1.0.

2
Un buon attributo senza cache per .NET stackoverflow.com/questions/10011780/…
Aran Mulholland

7

Questo frammento di JavaScript funziona perfettamente con jQuery e jQuery Mobile:

$.ajaxSetup({
    cache: false,
    headers: {
        'Cache-Control': 'no-cache'
    }
});

Inseriscilo da qualche parte nel tuo codice JavaScript (dopo che jQuery è stato caricato, e meglio prima di fare richieste AJAX) e dovrebbe aiutare.


6

Puoi anche risolvere questo problema modificando jQuery Ajax funzione procedendo come segue (a partire dall'1.7.1) all'inizio della funzione Ajax (la funzione inizia alla riga 7212). Questa modifica attiverà la funzione anti-cache integrata di jQuery per tutte le richieste POST.

(Lo script completo è disponibile all'indirizzo http://dl.dropbox.com/u/58016866/jquery-1.7.1.js .)

Inserisci sotto la riga 7221:

if (options.type === "POST") {
    options.cache = false;
}

Quindi modificare quanto segue (a partire dalla riga ~ 7497).

if (!s.hasContent) {
    // If data is available, append data to URL
    if (s.data) {
        s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
        // #9682: remove data so that it's not used in an eventual retry
        delete s.data;
    }

    // Get ifModifiedKey before adding the anti-cache parameter
    ifModifiedKey = s.url;

    // Add anti-cache in URL if needed
    if (s.cache === false) {
        var ts = jQuery.now(),
        // Try replacing _= if it is there
        ret = s.url.replace(rts, "$1_=" + ts);

        // If nothing was replaced, add timestamp to the end.
        s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
    }
}

Per:

// More options handling for requests with no content
if (!s.hasContent) {
    // If data is available, append data to URL
    if (s.data) {
        s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
        // #9682: remove data so that it's not used in an eventual retry
        delete s.data;
    }

    // Get ifModifiedKey before adding the anti-cache parameter
    ifModifiedKey = s.url;
}

// Add anti-cache in URL if needed
if (s.cache === false) {
    var ts = jQuery.now(),
    // Try replacing _= if it is there
    ret = s.url.replace(rts, "$1_=" + ts);

    // If nothing was replaced, add timestamp to the end.
    s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
}

4
Non è un buon approccio per cambiare jQuery o per qualsiasi motivo qualsiasi codice che non possiedi. (Ogni volta che si desidera aggiornare la versione, è necessario apportare nuovamente la modifica. (O Un altro sviluppatore si aggiorna e il programma non funziona))
andlrc

È un approccio perfettamente valido se hai bisogno della soluzione più rapida possibile per mitigare l'idiozia di Apple. Questa soluzione è stata utilizzata per risolvere il problema di un sito enorme che riceve milioni di accessi al giorno e ci ha permesso di farlo semplicemente modificando un file.
Sam Shiles,

Puoi guardarlo jQuery.ajaxPrefilere modificare la tua richiesta Ajax prima di inoltrarla. Puoi archiviare lo stesso con codice più ottimizzato e aggiornato.
andlrc,

1
Il problema con l'approccio preFilter è che è necessario registrare il filtro. Se hai uno script comune che viene eseguito quando ogni pagina viene caricata, allora va bene, ma in caso contrario dovresti impostare il prefiltro per ogni pagina che utilizza ajax. Lo scenario che ho affrontato, avevamo una posizione comune per il file JQ che è stato utilizzato come risorsa per oltre 7 singoli siti Web. A causa di questo errore stavamo perdendo migliaia di sterline l'ora e l'approccio che ho suggerito ci ha permesso di risolverlo nel più breve tempo possibile modificando UN file. Sono d'accordo con te in linea di principio, ma a volte devi essere pragmatico!
Sam Shiles,

È quindi possibile aggiungerlo nuovamente alla fine di quel file. Bene, l'hai risolto, la tua azienda deve essere felice per te.
andlrc,

5

Una rapida soluzione alternativa per i servizi GWT-RPC consiste nell'aggiungerlo a tutti i metodi remoti:

getThreadLocalResponse().setHeader("Cache-Control", "no-cache");

Molti di noi hanno centinaia di metodi remoti nelle loro implementazioni GWT. Esiste un modo universale per impostare l'intestazione del controllo cache per tutte le richieste?
Dirkoneill,

5

Questo è un aggiornamento della risposta di Baz1nga. Dato che options.datanon è un oggetto ma una stringa, ho appena fatto ricorso al concatenamento del timestamp:

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
  if (originalOptions.type == "post" || options.type == "post") {

    if (options.data && options.data.length)
      options.data += "&";
    else
      options.data = "";

    options.data += "timeStamp=" + new Date().getTime();
  }
});

1
Aggiungere timestamp è una cattiva idea, prova invece la soluzione di Dave.
Nicholas Shanks,

4

Per risolvere questo problema per le WebApp aggiunte alla schermata principale, è necessario seguire entrambe le soluzioni alternative più votate. La memorizzazione nella cache deve essere disattivata sul server Web per impedire che le nuove richieste vengano memorizzate nella cache in futuro e alcuni input casuali devono essere aggiunti a ogni richiesta post per consentire il passaggio delle richieste che sono già state memorizzate nella cache. Si prega di fare riferimento al mio post:

iOS6 - Esiste un modo per cancellare le richieste POST ajax memorizzate nella cache per webapp aggiunte alla schermata principale?

ATTENZIONE: a chiunque abbia implementato una soluzione alternativa aggiungendo un timestamp alle proprie richieste senza disattivare la memorizzazione nella cache sul server. Se la tua app viene aggiunta alla schermata principale, OGNI risposta verrà ora memorizzata nella cache, svuotare la cache di Safari non la cancella e non sembra scadere. A meno che qualcuno non abbia un modo per cancellarlo, sembra una potenziale perdita di memoria!


Tutte le risposte verranno memorizzate nella cache del file o della memoria sul telefono?
Eydun,

Questo non era il mio caso. Ho aggiunto un timestamp al mio URL (non ai parametri di post) e funziona perfettamente, sia durante la navigazione da Safari sia durante il salvataggio nella schermata principale.
ShadeTreeDeveloper

4

Cose che NON FUNZIONANO per me con un iPad 4 / iOS 6:

La mia richiesta contenente: Cache-Control: no-cache

//asp.net's:
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache)

Aggiunta di cache: false alla mia chiamata ajax jQuery

 $.ajax(
        {
            url: postUrl,
            type: "POST",
            cache: false,
            ...

Solo questo ha funzionato:

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

A cosa serve il voto negativo? Questa è una cache di informazioni importanti: false non funziona con iPad4 / iOS6 né //asp.net's: HttpContext.Current.Response.Cache.SetCacheability (HttpCacheability.NoCache)
Brian Ogden,

Per i posteri: a partire dal 2017, si $.ajax cache: falseaggiunge l'URL con il parametro query _=Date.prototype.getTime(), quindi non è più necessario aggiungere manualmente il timestamp.
cowbert,

3

Questo è il problema per GWT-RPC

class AuthenticatingRequestBuilder extends RpcRequestBuilder 
{
       @Override
       protected RequestBuilder doCreate(String serviceEntryPoint) 
       {
               RequestBuilder requestBuilder = super.doCreate(serviceEntryPoint);           
               requestBuilder.setHeader("Cache-Control", "no-cache");

               return requestBuilder;
       }
}

AuthenticatingRequestBuilder builder = new AuthenticatingRequestBuilder();
((ServiceDefTarget)myService).setRpcRequestBuilder(builder);    

2

La mia soluzione alternativa in ASP.NET (pagemethods, webservice, ecc.)

protected void Application_BeginRequest(object sender, EventArgs e)
{
    Response.Cache.SetCacheability(HttpCacheability.NoCache);
}

1

Mentre l'aggiunta di parametri cache-buster per rendere la richiesta diversa sembra una soluzione solida, sconsigliamo di farlo, poiché danneggerebbe qualsiasi applicazione che si basa sull'effettiva memorizzazione nella cache. Rendere l'output delle API le intestazioni corrette è la soluzione migliore, anche se leggermente più difficile dell'aggiunta di buster della cache ai chiamanti.


1
Mentre sarei d'accordo con te la maggior parte delle circostanze, direi che la vera soluzione a questo problema è che Apple implementi correttamente HTTP. Con questo in mente, non darei la colpa a molti sviluppatori per aver implementato la soluzione più semplice possibile fino a quel momento. Per me, modificare l'implementazione di jquery è stata la soluzione più semplice in quanto mi ha permesso di effettuare una modifica ed essere sicuro che fosse attivo per tutto il mio sito.
Sam Shiles,

1

Per quelli che usano Struts 1, ecco come ho risolto il problema.

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() {
    }

}

1

Sono stato in grado di risolvere il mio problema utilizzando una combinazione di $ .ajaxSetup e aggiungendo un timestamp all'URL del mio post (non al parametro / body post). Questo sulla base delle raccomandazioni delle risposte precedenti

$(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');
                }
            }
        });
    });
});

1

Penso che tu abbia già risolto il tuo problema, ma lasciami condividere un'idea sulla memorizzazione nella cache web.

È vero che puoi aggiungere molte intestazioni in ogni lingua che usi, lato server, lato client e puoi usare molti altri trucchi per evitare la memorizzazione nella cache web, ma pensa sempre che non puoi mai sapere da dove il client si sta connettendo al tuo server, non si sa mai se sta utilizzando una connessione "Hot-Spot" dell'hotel che utilizza Squid o altri prodotti di cache.

Se gli utenti utilizzano il proxy per nascondere la sua posizione reale, ecc ... il reale unico modo per evitare la memorizzazione nella cache è il timestamp nella richiesta anche se non viene utilizzato.

Per esempio:

/ajax_helper.php?ts=3211321456

Quindi ogni gestore di cache che devi passare non ha trovato lo stesso URL nel repository della cache e scarica nuovamente il contenuto della pagina.


Vecchia risposta, ma i miei due centesimi: questo è generalmente un buon consiglio e compreso dalla maggior parte degli sviluppatori web competenti, ma nel caso specifico di jQuery, se fai un $.ajaxe hai impostato le opzioni per avere {cache:false}allora jQuery stesso aggiungerà automaticamente un busting della cache dietro le quinte senza che tu abbia mai bisogno di fare nient'altro.
JakeGould

0

A seconda dell'app, puoi risolvere il problema ora in iOS 6 usando Safari> Avanzate> Web Inspector, quindi è utile in questa situazione.

Collega il telefono a Safari su un Mac, quindi utilizza il menu sviluppatore per risolvere il problema con l'app Web.

Cancella i dati del sito Web sull'iPhone dopo l'aggiornamento a iOS6, inclusi quelli specifici dell'app tramite una visualizzazione Web. Solo un'app ha avuto un problema e questo è stato risolto durante il test IOS6 Beta, da allora nessun problema reale.

Potrebbe essere necessario esaminare anche la tua app, controllare NSURLCache se in una visualizzazione Web in un'app personalizzata.

https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSURLCache_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40003754

Immagino che a seconda della vera natura del tuo problema, implementazione, ecc.

Rif: $ .ajax chiama


Sebbene questo non affronti direttamente la domanda originale, sono informazioni molto utili per essere in grado di risolvere i problemi dei dispositivi in ​​generale, quindi sto votando.
Kris Giesing,

0

Ho trovato una soluzione alternativa che mi incuriosisce sul perché funzioni. Prima di leggere la risposta di Tadej riguardante il servizio web ASP.NET, stavo cercando di trovare qualcosa che potesse funzionare.

E non sto dicendo che sia una buona soluzione, ma volevo solo documentarlo qui.

pagina principale: include una funzione JavaScript, checkStatus (). Il metodo chiama un altro metodo che utilizza una chiamata AJAX jQuery per aggiornare il contenuto html. Ho usato setInterval per chiamare checkStatus (). Certo, ho riscontrato un problema con la cache.

Soluzione: utilizzare un'altra pagina per chiamare l'aggiornamento.

Nella pagina principale, ho impostato una variabile booleana, runUpdate, e ho aggiunto quanto segue al tag body:

<iframe src="helper.html" style="display: none; visibility: hidden;"></iframe>

Nel file di helper.html:

<meta http-equiv="refresh" content="5">
<script type="text/javascript">
    if (parent.runUpdate) { parent.checkStatus(); }
</script>

Quindi, se checkStatus () viene chiamato dalla pagina principale, ottengo il contenuto memorizzato nella cache. Se chiamo checkStatus dalla pagina figlio, ottengo contenuto aggiornato.


0

Mentre le mie pagine di accesso e registrazione funzionano come un incantesimo in Firefox, IE e Chrome ... Ho avuto difficoltà con questo problema in Safari per IOS e OSX, alcuni mesi fa ho trovato una soluzione alternativa su SO.

<body onunload="">

O tramite javascript

<script type="text/javascript">
window.onunload = function(e){
    e.preventDefault();
    return;
};
</script>   

Questa è una cosa brutta ma funziona per un po '.

Non so perché, ma restituendo null onunloadall'evento la pagina non viene memorizzata nella cache in Safari.


0

Abbiamo scoperto che iPhone e iPad più vecchi, con iOS 9 e 10, occasionalmente restituiscono risultati AJAX vuoti, forse a causa della riduzione della velocità della CPU di Apple. Quando restituisce il risultato vuoto, iOS non chiama il server, come se restituisse un risultato dalla cache. La frequenza varia ampiamente, da circa il 10% al 30% delle chiamate AJAX ritornano vuote.

La soluzione è difficile da credere. Aspetta 1 secondo e chiama di nuovo. Nei nostri test, è stata necessaria solo una ripetizione, ma abbiamo scritto il codice per chiamare fino a 4 volte. Non siamo sicuri se è necessaria l'attesa 1s, ma non volevamo rischiare di sovraccaricare il nostro server con raffiche di chiamate ripetute.

Abbiamo riscontrato che il problema si è verificato con due diverse chiamate AJAX, chiamando diversi file API con dati diversi. Ma sono preoccupato che possa accadere su qualsiasi chiamata AJAX. Semplicemente non lo sappiamo perché non controlliamo ogni risultato AJAX e non testiamo ogni chiamata più volte sui vecchi dispositivi.

Entrambi i problemi con le chiamate AJAX stavano usando: POST, in modo asincrono = vero, setRequestHeader = ('Content-Type', 'application / x-www-form-urlencoded')

Quando si verifica il problema, di solito c'è solo una chiamata AJAX in corso. Quindi non è dovuto alla sovrapposizione di chiamate AJAX. A volte il problema si verifica quando il dispositivo è occupato, ma a volte no, e senza DevTools non sappiamo davvero cosa sta succedendo in quel momento.

iOS 13 non lo fa, né Chrome o Firefox. Non abbiamo dispositivi di test con iOS 11 o 12. Forse qualcun altro potrebbe testarli?

Sto notando questo qui perché questa domanda è il miglior risultato di Google durante la ricerca di questo problema.


-1

Ha funzionato con ASP.NET solo dopo aver aggiunto l' pragma:no-cacheintestazione in IIS . Cache-Control: no-cachenon era abbastanza.


-2

Suggerisco una soluzione alternativa per modificare la firma della funzione in modo che sia simile a questa:

getNewRecordID (intRecordType, strTimestamp) e quindi passa sempre anche un parametro TimeStamp e scarta quel valore sul lato server. Questo risolve il problema.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.