¿Safari en iOS 6 almacena en caché los resultados de $ .ajax?

1091

Desde la actualización a iOS 6, vemos que la vista web de Safari se toma la libertad de almacenar en caché las $.ajaxllamadas. Esto está en el contexto de una aplicación PhoneGap, por lo que utiliza Safari WebView. Nuestras $.ajaxllamadas son POSTmétodos y tenemos la caché configurada en falso {cache:false}, pero esto sigue sucediendo. Intentamos agregar manualmente TimeStampa los encabezados, pero no ayudó.

Investigamos más y descubrimos que Safari solo devuelve resultados almacenados en caché para servicios web que tienen una firma de función que es estática y no cambia de una llamada a otra. Por ejemplo, imagina una función llamada algo como:

getNewRecordID(intRecordType)

Esta función recibe los mismos parámetros de entrada una y otra vez, pero los datos que devuelve deben ser diferentes cada vez.

Debe estar en la prisa de Apple para hacer que iOS 6 se desarrolle de manera impresionante, se pusieron demasiado contentos con la configuración de la caché. ¿Alguien más ha visto este comportamiento en iOS 6? Si es así, ¿qué lo está causando exactamente?


La solución alternativa que encontramos fue modificar la firma de la función para que sea algo como esto:

getNewRecordID(intRecordType, strTimestamp)

y luego siempre pase también un TimeStampparámetro, y simplemente descarte ese valor en el lado del servidor. Esto soluciona el problema.

23
  • 191
    Esto es absolutamente impactante. También hemos pasado un par de horas tratando de averiguar qué es lo que dejó de funcionar. Nuestro inicio de sesión AJAX que hace un POST (y tiene encabezados para evitar el almacenamiento en caché también) está siendo almacenado en caché por Safari, por lo que solo devuelve el mismo JSON que la última vez sin siquiera probar el servidor ... ¡increíble! Tendremos que hackear una solución, pero nunca debe almacenar en caché un POST, es una locura. Kieran 20/09/12 a las 14:55
  • dieciséis
    Publique su solución como una respuesta en lugar de una actualización de la pregunta. ChrisF 21/09/12 a las 14:40
  • 50
    Las solicitudes POST no son idempotentes, lo que significa que no deben almacenarse en caché a menos que la respuesta indique específicamente hacerlo a través de sus encabezados de respuesta. James M. Greene 21/09/12 a las 15:14
  • 6
    Para que Apple solucione este problema, presente un error en bugreport.apple.com . Yo hice lo mismo. Mathias Bynens 23/09/12 a las 10:13
  • 11
    Mark Nottingham (presidente del grupo de trabajo IETF HTTPbis) escribió una publicación de blog interesante sobre esto hoy: mnot.net/blog/2012/09/24/caching_POSTBenjamin Brizzi 24/09/12 a las 15:02
448

Después de un poco de investigación, resulta que Safari en iOS6 almacenará en caché los POST que no tienen encabezados de Cache-Control o incluso "Cache-Control: max-age = 0".

La única forma que he encontrado de evitar que este almacenamiento en caché ocurra a nivel global en lugar de tener que piratear cadenas de consulta aleatorias al final de las llamadas de servicio es establecer "Cache-Control: no-cache".

Entonces:

  • Sin Cache-Control o encabezados Expires = iOS6 Safari almacenará en caché
  • Cache-Control max-age = 0 y un inmediato Expires = iOS6 Safari almacenará en caché
  • Cache-Control: no-cache = iOS6 Safari NO almacenará en caché

Sospecho que Apple se está aprovechando de esto de la especificación HTTP en la sección 9.5 sobre POST:

Responses to this method are not cacheable, unless the response includes appropriate Cache-Control or Expires header fields. However, the 303 (See Other) response can be used to direct the user agent to retrieve a cacheable resource.

Entonces, en teoría, puede almacenar en caché las respuestas POST ... quién sabía. Pero ningún otro fabricante de navegadores pensó que sería una buena idea hasta ahora. Pero eso NO tiene en cuenta el almacenamiento en caché cuando no se configuran los encabezados Cache-Control o Expires, solo cuando hay algunos configurados. Entonces debe ser un error.

A continuación se muestra lo que uso en la parte correcta de mi configuración de Apache para apuntar a la totalidad de mi API porque, como sucede, en realidad no quiero almacenar nada en caché, incluso get. Lo que no sé es cómo configurar esto solo para POST.

Header set Cache-Control "no-cache"

Actualización: Acabo de notar que no señalé que es solo cuando el POST es el mismo, así que cambie cualquiera de los datos POST o URL y estará bien. Por lo tanto, como se mencionó en otra parte, simplemente puede agregar algunos datos aleatorios a la URL o un poco de datos POST.

Actualización: puede limitar el "sin caché" solo a los POST si lo desea en Apache:

SetEnvIf Request_Method "POST" IS_POST
Header set Cache-Control "no-cache" env=IS_POST
11
  • 7
    Veo a dónde va Apple con esto, pero estamos viendo respuestas en caché a las solicitudes POST incluso cuando nuestras respuestas no incluían ningún encabezado de Cache-Control o Expires. Es esta instancia iOS6 no debe almacenar en caché y enviar todas las solicitudes. Esto no está ocurriendo. Kango_V 20/09/12 a las 16:52
  • 139
    La parte de la especificación HTTP que citó no justifica el comportamiento de almacenamiento en caché de iOS 6. El comportamiento predeterminado debería ser no almacenar en caché las respuestas POST (es decir, cuando el encabezado "Cache-Control" no está definido). El comportamiento viola la especificación y debe considerarse un error. Cualquiera que cree servicios web xml / json api debería decorar sus respuestas POST con "Cache-control: no-cache" para solucionar este problema. David H 20/09/12 a las 23:06
  • 39
    Las solicitudes POST no son idempotentes, lo que significa que no deben almacenarse en caché a menos que la respuesta indique específicamente hacerlo a través de sus encabezados de respuesta. James M. Greene 21/09/12 a las 15:13
  • 4
    Como dice David, es una clara violación de la oración que citó. Si no hay "Cache-Control o campos de encabezado Expires", los encabezados apropiados, obviamente, no están incluidos. Sin embargo, su propia investigación muestra que se almacena en caché en ese escenario. Edite su respuesta. Matthew Flaschen 22 de septiembre de 2012 a las 6:16
  • 3
    ¿Alguien sabe cuánto tiempo se almacena en caché el resultado en un dispositivo? Intenté matar safari y reiniciar mi teléfono, pero aún está almacenado en caché. Sé que funciona borrando la memoria caché del navegador, pero me pregunto cuánto tiempo les tomará a los usuarios que alguna vez tuvieron el problema antes de que desaparezca. No todos pensarán en limpiar su caché ...Daniel Hallqvist 25 de septiembre de 2012 a las 18:22
147

Espero que esto pueda ser de utilidad para que otros desarrolladores se golpeen la cabeza contra la pared en este caso. Descubrí que cualquiera de los siguientes evita que Safari en iOS 6 almacene en caché la respuesta POST:

  • agregando [cache-control: no-cache] en los encabezados de la solicitud
  • agregar un parámetro de URL variable como la hora actual
  • agregando [pragma: no-cache] en los encabezados de respuesta
  • agregando [cache-control: no-cache] en los encabezados de respuesta

Mi solución fue la siguiente en mi Javascript (todas mis solicitudes AJAX son POST).

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

También agrego el encabezado [pragma: no-cache] a muchas de las respuestas de mi servidor.

Si usa la solución anterior, tenga en cuenta que cualquier llamada $ .ajax () que realice y que esté configurada en global: false NO usará la configuración especificada en $ .ajaxSetup (), por lo que deberá agregar los encabezados nuevamente.

6
  • 4
    Esta es LA solución CORRECTA al error. El error es que iOS 6 atenderá las solicitudes POST desde su caché en lugar de enviarlas al servidor. El error no es que almacene en caché las respuestas de las solicitudes POST (lo cual está permitido). Si aún desea que las respuestas a las solicitudes POST se recuperen de la caché para las solicitudes GET posteriores a ese URI, use esta solución. Nicholas Shanks 12/11/12 a las 16:32
  • 2
    Esto funciona para mí, pero no entiendo cómo. Ya había especificado cache: false en mi ajaxSetup, y mirando los encabezados de solicitud, eso se reduce a Cache-Control: no-cache y Pragma: no-cache, pero aún se almacenará en caché en el iPad. Luego, cuando agrego encabezados: {"cache-control": "no-cache"} en ajaxSetup, duplica el encabezado Cache-Control para que sea "no-cache, no-cache" y detiene el almacenamiento en caché. ¿Que esta pasando aqui? Tom W Hall 26/11/12 a las 22:18
  • Funciona perfectamente, también puede agregar a la solicitud como un parámetro $ .ajax ({tipo: 'POST', encabezados: {'cache-control': 'no-cache'}, etc.})George Filippakos 2 de enero de 2013 a las 13:05
  • ¿Qué es [pragma: no-cache]? ¿Para qué se utiliza la clave pragma? zakdances 19/0313 a las 20:34
  • También creo que este es el mejor enfoque, en lugar de una solución con un parámetro adicional. Hemos agregado esto solo en las llamadas donde lo necesitábamos, para las llamadas que siempre tienen el mismo retorno, el almacenamiento en caché es probablemente algo bueno para el usuario final. germankiwi 20 de mayo de 2013 a las 22:37
68

Solución simple para todas sus solicitudes de servicios web, asumiendo que está usando 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()
    }));
});

Lea más sobre la llamada de prefiltro de jQuery aquí .

Si no está utilizando jQuery, consulte los documentos de la biblioteca de su elección. Pueden tener una funcionalidad similar.

9
  • 3
    No me funciona, el servidor responde: "JSON primitivo no válido: marca de tiempo" asp.net / iis 7.5Alexandre 24 de septiembre de 2012 a las 0:10
  • 3
    ¿qué pasa con el $ .ajax ({"caché": falso ...})? ¿Funcionará si agrega un _ = [TIMESTAMP]? (No tengo un dispositivo de este tipo para probarlo)Karussell 24 de septiembre de 2012 a las 12:59
  • He publicado una implementación completa de la solución propuesta por Karussell. Vea mi respuesta a continuación. Sam Shiles 27/09/12 a las 14:45
  • 1
    @Karussell. Intenté configurar $ .ajax ({"cache": false ...}). Esto no resuelve el problema de las solicitudes POST en iOS6. Presumiblemente porque JQuery según sus documentos asume que ningún navegador es lo suficientemente estúpido como para almacenar en caché las solicitudes de publicación. "Las páginas obtenidas con POST nunca se almacenan en caché, por lo que la caché y las opciones ifModified en jQuery.ajaxSetup () no tienen ningún efecto en estas solicitudes". Brett Hannah 2/10/12 a las 11:02
  • 1
    Esto no funciona. No fusiona los parámetros de publicación. La publicación de Dave es una mejor solución. Chris Muench 15/10/12 a las 23:33
44

También tuve este problema en una aplicación PhoneGap . Lo resolví usando la función JavaScript getTime()de la siguiente manera:

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

Perdí algunas horas resolviendo esto. Hubiera sido bueno por parte de Apple notificar a los desarrolladores sobre este problema de almacenamiento en caché.

2
  • 1
    Iba a comentar sobre el uso {cache:false}como una opción de $.post()o $.ajaxSetup(), pero de acuerdo con los documentos , estos argumentos se ignoran; jQuery 'nunca almacenará en caché' las solicitudes de publicación, pero no tiene en cuenta el navegador. Quizás una opción más ordenada sería agregar una marca de tiempo a las solicitudes que usan $.ajaxPrefilter(). cthulhu 21 de septiembre de 2012 a las 8:33
  • Pasé casi 5 horas para solucionar este problema, y ​​finalmente agregar la marca de tiempo hará el truco function send_ajax(my_data,refresh) ... consulte aquí stackoverflow.com/questions/14733772/…rusly 23/11/2013 a las 15:01
42

Tuve el mismo problema con una aplicación web que obtenía datos del servicio web ASP.NET

Esto funcionó para mí:

public WebService()
{
    HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    ...
}
3
  • 2
    ¡Muchos gracias! Me estaba volviendo loco tratando de averiguar por qué el iPhone actuaba de manera tan diferente a cualquier otra plataforma. Esta solución específica de ASP.NET me ahorró mucho tiempo. Mark Brittingham 11/11/12 a las 18:14
  • No funcionó para iOS6, vea mi respuesta hacia el final del hiloBrian Ogden 29 de abril de 2013 a las 6:41
  • 1
    ¡¡¡¡Por favor!!!! Ponga una condición para aplicar esto solo en IOS 6, la caché de contenido es vital para cualquier aplicación. Alexandre 8/04/2015 a las 22:27
24

Finalmente, tengo una solución a mi problema de carga.

En JavaScript:

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

En PHP :

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

De mi propia publicación de blog iOS 6.0 almacenando en caché las solicitudes POST de Ajax :

Cómo solucionarlo: existen varios métodos para evitar el almacenamiento en caché de solicitudes. El método recomendado es agregar un encabezado sin caché. Así es como se hace.

jQuery:

Verifique iOS 6.0 y configure el encabezado Ajax de esta manera:

$.ajaxSetup({ cache: false });

ZeptoJS:

Verifique iOS 6.0 y configure el encabezado Ajax de esta manera:

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

Lado del servidor

Java:

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

Asegúrese de agregar esto en la parte superior de la página antes de que se envíen datos al cliente.

.NETO

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.
1
7

Este fragmento de JavaScript funciona muy bien con jQuery y jQuery Mobile:

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

Simplemente colóquelo en algún lugar de su código JavaScript (después de que se cargue jQuery, y mejor antes de realizar solicitudes AJAX) y debería ayudar.

6

También puede solucionar este problema modificando la función jQuery Ajax haciendo lo siguiente (a partir de 1.7.1) en la parte superior de la función Ajax (la función comienza en la línea 7212). Este cambio activará la función anti-caché incorporada de jQuery para todas las solicitudes POST.

(El guión completo está disponible en http://dl.dropbox.com/u/58016866/jquery-1.7.1.js).

Inserte debajo de la línea 7221:

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

Luego modifique lo siguiente (comenzando en la línea ~ 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 : "");
    }
}

Para:

// 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 : "");
}
5
  • 4
    No es un buen enfoque cambiar jQuery o cualquier código que no sea de su propiedad. (Cada vez que desee actualizar la versión, tendrá que realizar el cambio nuevamente. (O Otro desarrollador se actualiza y el programa no funciona))andlrc 31/10/12 a las 16:40
  • Es un enfoque perfectamente válido si necesita la solución más rápida posible para mitigar la idiotez de Apple. Esta solución se ha utilizado para resolver el problema de un sitio masivo que recibe millones de visitas al día y nos permitió hacerlo con solo hacer un cambio en un archivo. Sam Shiles 1/11/12 a las 14:53
  • Puede ver jQuery.ajaxPrefilerque le permite modificar su solicitud ajax justo antes de realizarla. Puede archivar el mismo con un código seguro más optimizado y actualizado. andlrc 1 nov. 12 a las 15:16
  • 1
    El problema con el enfoque de preFilter es que necesita registrar el filtro. Si tiene un script común que se ejecuta cuando se carga cada página, entonces está bien, pero si no lo hace, tendría que configurar el preFiltro para cada página que usa ajax. En el escenario al que me enfrenté, teníamos una ubicación común para el archivo JQ que se utilizó como recurso para más de 7 sitios web individuales. Estábamos perdiendo miles de libras por hora debido a este error y el enfoque que sugerí nos permitió resolverlo en el menor tiempo posible cambiando UN archivo. Estoy de acuerdo contigo en principio, ¡pero a veces tienes que ser pragmático! Sam Shiles 1/11/12 a las 15:28
  • Luego, puede agregarlo nuevamente al final de ese archivo. Bien lo resolviste, tu empresa debe estar feliz por ti. andlrc 1/11/12 a las 15:41
5

Una solución rápida para los servicios GWT-RPC es agregar esto a todos los métodos remotos:

getThreadLocalResponse().setHeader("Cache-Control", "no-cache");
1
  • La mayoría de nosotros tenemos cientos de métodos remotos en sus implementaciones de GWT. ¿Existe una forma universal de establecer el encabezado de control de caché para todas las solicitudes? dirkoneill 9/11/12 a las 4:37
5

Esta es una actualización de la respuesta de Baz1nga. Dado options.dataque no es un objeto sino una cadena, simplemente recurrí a concatenar la marca de tiempo:

$.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
  • 1
    Agregar marcas de tiempo es una mala idea, pruebe la solución de Dave en su lugar. Nicholas Shanks 12/11/12 a las 16:38
4

Para resolver este problema para las aplicaciones web agregadas a la pantalla de inicio, se deben seguir las dos soluciones alternativas más votadas. El almacenamiento en caché debe desactivarse en el servidor web para evitar que se almacenen en caché nuevas solicitudes en el futuro y es necesario agregar alguna entrada aleatoria a cada solicitud de publicación para que las solicitudes que ya se hayan almacenado en caché puedan procesarse. Consulte mi publicación:

iOS6: ¿hay alguna manera de borrar las solicitudes POST de ajax almacenadas en caché para la aplicación web agregada a la pantalla de inicio?

ADVERTENCIA: para cualquiera que haya implementado una solución alternativa agregando una marca de tiempo a sus solicitudes sin desactivar el almacenamiento en caché en el servidor. Si su aplicación se agrega a la pantalla de inicio, CADA respuesta de publicación ahora se almacenará en caché, borrar la caché de Safari no la borra y no parece que caduque. A menos que alguien tenga una forma de borrarlo, ¡esto parece una posible pérdida de memoria!

2
  • ¿Todas las respuestas se almacenarán en caché en un archivo o en la memoria del teléfono? Eydun 5/10/12 a las 11:56
  • Este no fue mi caso. Agregué una marca de tiempo a mi URL (no a los parámetros de publicación) y funciona bien, tanto al navegar desde Safari como al guardar en la pantalla de inicio. ShadeTreeDeveloper 19/01/2013 a las 17:17
4

Cosas que NO ME FUNCIONARON con un iPad 4 / iOS 6:

Mi solicitud contiene: Cache-Control: no-cache

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

Agregar caché: falso a mi llamada jQuery ajax

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

Solo esto hizo el truco:

var currentTime = new Date();
var n = currentTime.getTime();
postUrl = "http://www.example.com/test.php?nocache="+n;
$.post(postUrl, callbackFunction);
2
  • ¿Para qué es el voto negativo? Esta es una caché de información importante: false no funciona con iPad4 / iOS6 ni tampoco //asp.net's: HttpContext.Current.Response.Cache.SetCacheability (HttpCacheability.NoCache)Brian Ogden 10 de mayo de 2013 a las 7:40 p.m.
  • Para la posteridad: a partir de 2017, $.ajax cache: falseagrega la URL con el parámetro de consulta _=Date.prototype.getTime(), por lo que ya no debería ser necesario agregar manualmente la marca de tiempo. cowbert 15 de enero de 2018 a las 22:02
3

Esa es la solución para 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

Mi solución en ASP.NET (métodos de página, servicio web, etc.)

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

Si bien agregar parámetros de eliminación de caché para hacer que la solicitud se vea diferente parece una solución sólida, desaconsejaría hacerlo, ya que dañaría cualquier aplicación que se base en el almacenamiento en caché real. Hacer que las API generen los encabezados correctos es la mejor solución posible, incluso si eso es un poco más difícil que agregar destructores de caché a las personas que llaman.

1
  • 1
    Si bien estoy de acuerdo con usted en la mayoría de las circunstancias, diría que la verdadera solución a este problema es que Apple implemente HTTP correctamente. Con esto en mente, no culparía a muchos desarrolladores por implementar la solución más simple posible hasta ese momento. Para mí, modificar la implementación de jquery fue la solución más simple, ya que me permitió hacer una edición y estar seguro de que estaba activa para todo mi sitio. Sam Shiles 28 de septiembre de 2012 a las 7:32
1

Para aquellos que usan Struts 1, así es como solucioné el 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

Pude solucionar mi problema usando una combinación de $ .ajaxSetup y agregando una marca de tiempo a la URL de mi publicación (no a los parámetros / cuerpo de la publicación). Esto en base a las recomendaciones de respuestas anteriores.

$(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

Creo que ya resolvió su problema, pero permítame compartirle una idea sobre el almacenamiento en caché web.

Es cierto que puede agregar muchos encabezados en cada idioma que usa, del lado del servidor, del lado del cliente, y puede usar muchos otros trucos para evitar el almacenamiento en caché web, pero siempre piense que nunca se puede saber desde dónde se conecta el cliente a su servidor. nunca se sabe si está usando una conexión de hotel "Hot-Spot" que usa Squid u otros productos de almacenamiento en caché.

Si los usuarios están usando un proxy para ocultar su posición real, etc., la única forma real de evitar el almacenamiento en caché es la marca de tiempo en la solicitud también si no se usa.

Por ejemplo:

/ajax_helper.php?ts=3211321456

Luego, cada administrador de caché que tiene que pasar no encontró la misma URL en el repositorio de caché y volvió a descargar el contenido de la página.

1
  • Respuesta anterior, pero mis dos centavos: este es generalmente un buen consejo y es entendido por la mayoría de los desarrolladores web competentes, pero en el caso específico de jQuery, si $.ajaxcrea una y ha configurado las opciones para tener, {cache:false}entonces jQuery agregará automáticamente una eliminación de caché detrás de escena sin necesidad de hacer nada más. Giacomo1968 3 de diciembre de 2015 a las 7:30
0

Dependiendo de la aplicación, puede solucionar el problema ahora en iOS 6 usando Safari> Avanzado> Inspector web, por lo que es útil en esta situación.

Conecte el teléfono a Safari en una Mac y luego use el menú de desarrollador para solucionar problemas de la aplicación web.

Borre los datos del sitio web en el iPhone después de la actualización a iOS6, incluso los datos específicos de la aplicación mediante una vista web. Solo una aplicación tuvo un problema y esto lo resolvió durante las pruebas de IOS6 Beta hace mucho tiempo, desde entonces no hubo problemas reales.

Es posible que también deba mirar su aplicación, consulte NSURLCache si está en un WebView en una aplicación personalizada.

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

Supongo que dependiendo de la verdadera naturaleza de su problema, implementación, etc.

Ref: $ .ajax llamadas

1
  • Si bien esto no aborda directamente la pregunta original, es información muy útil para poder solucionar problemas en los dispositivos en general, por lo que la votaré a favor. Kris Giesing 7/10/12 a las 20:33
0

Encontré una solución que me da curiosidad por saber por qué funciona. Antes de leer la respuesta de Tadej sobre el servicio web ASP.NET, estaba tratando de encontrar algo que funcionara.

Y no digo que sea una buena solución, solo quería documentarlo aquí.

página principal: incluye una función de JavaScript, checkStatus (). El método llama a otro método que usa una llamada jQuery AJAX para actualizar el contenido html. Usé setInterval para llamar checkStatus (). Por supuesto, me encontré con el problema del almacenamiento en caché.

Solución: use otra página para llamar a la actualización.

En la página principal, configuré una variable booleana, runUpdate y agregué lo siguiente a la etiqueta del cuerpo:

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

En el de helper.html:

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

Entonces, si se llama a checkStatus () desde la página principal, obtengo el contenido en caché. Si llamo a checkStatus desde la página secundaria, obtengo contenido actualizado.

0

Si bien mis páginas de inicio de sesión y registro funcionan a la perfección en Firefox, IE y Chrome ... He estado luchando con este problema en Safari para IOS y OSX, hace unos meses encontré una solución en el SO.

<body onunload="">

O a través de javascript

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

Esto es algo feo pero funciona por un tiempo.

No sé por qué, pero al devolver un valor nulo al onunloadevento, la página no se almacena en caché en Safari.

0

Descubrimos que los iPhones y iPads más antiguos, que ejecutan las versiones 9 y 10 de iOS, ocasionalmente devuelven resultados AJAX en blanco falsos, tal vez debido a que Apple redujo la velocidad de la CPU. Al devolver el resultado en blanco, iOS no llama al servidor, como si estuviera devolviendo un resultado de la caché. La frecuencia varía ampliamente, desde aproximadamente el 10% al 30% de las llamadas AJAX se devuelven en blanco.

La solución es difícil de creer. Espere 1 segundo y vuelva a llamar. En nuestras pruebas, solo una repetición fue todo lo que se necesitó, pero escribimos el código para llamar hasta 4 veces. No estamos seguros de si se requiere la espera de 1, pero no queríamos arriesgarnos a sobrecargar nuestro servidor con ráfagas de llamadas repetidas.

Descubrimos que el problema ocurrió con dos llamadas AJAX diferentes, llamando a diferentes archivos API con diferentes datos. Pero me preocupa que pueda suceder en cualquier llamada AJAX. Simplemente no lo sabemos porque no inspeccionamos todos los resultados de AJAX y no probamos cada llamada varias veces en dispositivos antiguos.

Ambos problemas de llamadas AJAX estaban usando: POST, Asynchronously = true, setRequestHeader = ('Content-Type', 'application / x-www-form-urlencoded')

Cuando ocurre el problema, generalmente solo hay una llamada AJAX en curso. Por tanto, no se debe a la superposición de llamadas AJAX. A veces, el problema ocurre cuando el dispositivo está ocupado, pero a veces no, y sin DevTools no sabemos realmente qué está sucediendo en ese momento.

iOS 13 no hace esto, ni Chrome o Firefox. No tenemos ningún dispositivo de prueba con iOS 11 o 12. ¿Quizás alguien más podría probarlos?

Estoy señalando esto aquí porque esta pregunta es el resultado principal de Google al buscar este problema.

-1

Funcionó con ASP.NET solo después de agregar el pragma:no-cacheencabezado en IIS . Cache-Control: no-cacheno fue suficiente.

-2

Sugiero una solución alternativa para modificar la firma de la función para que sea algo como esto:

getNewRecordID (intRecordType, strTimestamp) y luego siempre pasa también un parámetro TimeStamp, y simplemente descarta ese valor en el lado del servidor. Esto soluciona el problema.

0