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


1072

Desde la actualización a iOS 6, estamos viendo 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 está utilizando Safari WebView. Nuestras $.ajaxllamadas son POSTmétodos y tenemos el caché establecido en falso {cache:false}, pero aún así esto está sucediendo. Intentamos agregar manualmente TimeStampa los encabezados pero no sirvió de nada.

Investigamos más y descubrimos que Safari solo está devolviendo resultados en caché para servicios web que tienen una firma de función que es estática y no cambia de llamada a llamada. Por ejemplo, imagine 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 apurado por Apple para hacer que iOS 6 se deslice de manera impresionante, se alegraron demasiado con la configuración de caché. ¿Alguien más ha visto este comportamiento en iOS 6? Si es así, ¿qué lo está causando exactamente?


La solución que encontramos fue modificar la firma de la función para que sea así:

getNewRecordID(intRecordType, strTimestamp)

y luego siempre pasa un TimeStampparámetro también, y simplemente descarta ese valor en el lado del servidor. Esto funciona alrededor del problema. ¡Espero que esto ayude a otra pobre alma que pasa 15 horas en este tema como lo hice yo!


190
Esto es absolutamente impactante. También acabamos de pasar un par de horas tratando de resolver qué algo dejó de funcionar. Safari está almacenando en caché nuestro inicio de sesión AJAX que hace una POST (y también tiene encabezados para evitar el almacenamiento en caché), por lo que solo devuelve el mismo JSON que hizo la última vez sin siquiera probar el servidor ... ¡increíble! Tendremos que hackear una solución, pero nunca debes almacenar en caché una POST, es una locura.
Kieran

16
Publique su solución como una respuesta en lugar de una actualización de la pregunta.
ChrisF

50
Las solicitudes POST no son idempotentes, lo que significa que no deben almacenarse en caché a menos que la respuesta lo recomiende específicamente a través de sus encabezados de respuesta.
James M. Greene

66
Para que Apple solucione esto, presente un error en bugreport.apple.com . Yo hice lo mismo.
Mathias Bynens el

11
Mark Nottingham (presidente del grupo de trabajo IETF HTTPbis) escribió una interesante publicación de blog sobre esto hoy: mnot.net/blog/2012/09/24/caching_POST
Benjamin Brizzi

Respuestas:


447

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 hackear cadenas de consulta aleatorias al final de las llamadas de servicio es establecer "Cache-Control: no-cache".

Entonces:

  • Sin control de caché o encabezados con caducidad = Safari iOS6 se almacenará en caché
  • Cache-Control max-age = 0 y caduca inmediatamente = iOS6 Safari almacenará en caché
  • Cache-Control: no-cache = iOS6 Safari NO almacenará en caché

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

Las respuestas a este método no se pueden almacenar en caché, a menos que la respuesta incluya los campos de encabezado Cache-Control o Expires apropiados. Sin embargo, la respuesta 303 (Ver otros) se puede usar para indicar al agente de usuario que recupere un recurso almacenable en caché.

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

A continuación se muestra lo que uso en el bit correcto de mi configuración de Apache para apuntar a toda mi API porque, en realidad, no quiero almacenar en caché nada, ni siquiera lo consigo. 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 la POST es la misma, así que cambie cualquiera de los datos de la POST o la URL y estará bien. Entonces, como se mencionó en otro lugar, solo puede agregar algunos datos aleatorios a la URL o un poco de datos POST.

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

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

77
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 control de caché o caduca. Es esta instancia iOS6 no debe almacenar en caché y enviar cada solicitud. Esto no está ocurriendo.
Kango_V

138
La parte de la especificación HTTP que citó no justifica el comportamiento de almacenamiento en caché de iOS 6. El comportamiento predeterminado debe ser no almacenar en caché las respuestas POST (es decir, cuando el encabezado "Cache-Control" no está definido). El comportamiento viola las especificaciones y debe considerarse un error. Cualquier persona que cree servicios web xml / json api debe decorar sus respuestas POST con "Cache-control: no-cache" para solucionar este problema.
David H

39
Las solicitudes POST no son idempotentes, lo que significa que no deben almacenarse en caché a menos que la respuesta lo recomiende específicamente a través de sus encabezados de respuesta.
James M. Greene

44
Como dice David, es una clara violación de la oración que citó. Si no hay "campos de encabezado de control de caché o caduca", obviamente no se incluyen dichos encabezados. Sin embargo, su propia investigación muestra que se almacena en caché en ese escenario. Por favor edite su respuesta.
Matthew Flaschen

3
¿Alguien sabe cuánto tiempo se almacena en caché el resultado en un dispositivo? He intentado matar a Safari y reiniciar mi teléfono, pero todavía está en caché. Sé que funciona con la eliminación de la memoria caché del navegador, pero me pregunto cuánto tiempo llevará a los usuarios que alguna vez tuvieron el problema antes de que desaparezca. No todo el mundo pensará en limpiar su caché ...
Daniel Hallqvist

146

Espero que esto pueda ser útil para otros desarrolladores que 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 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 de 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 que esté establecida en global: false NO usará la configuración especificada en $ .ajaxSetup (), por lo que deberá agregar los encabezados nuevamente.


44
Esta es la solución correcta para el error. El error es que iOS 6 atenderá las solicitudes POST de su caché en lugar de enviarlas al servidor. El error no es que almacena en caché las respuestas de las solicitudes POST (que está permitido). Si aún desea respuestas a las solicitudes POST recuperadas de la caché para solicitudes GET posteriores a ese URI, use esta solución.
Nicholas Shanks

2
Esto funciona para mí, pero no entiendo cómo. Ya había especificado caché: falso 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 el

Funciona perfectamente: también puede agregar a la solicitud como parámetro $ .ajax ({tipo: 'POST', encabezados: {'cache-control': 'no-cache'}, etc.})
George Filippakos

¿Qué es [pragma: no-cache]? ¿Para qué se usa la clave pragma?
zakdances

También creo que este es el mejor enfoque, en lugar de una solución alternativa con un parámetro adicional. Hemos agregado esto solo a 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

67

Solución simple para todas sus solicitudes de servicio web, suponiendo que esté utilizando 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 del prefiltro jQuery aquí .

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


3
No me funciona, el servidor responde: "JSON primitivo no válido: timeStamp" asp.net / iis 7.5
Alexandre

3
¿Qué pasa con el $ .ajax ({"caché": falso ...})? ¿funcionará ya que agrega un _ = [TIMESTAMP]? (No tengo un dispositivo para probarlo)
Karussell

He publicado una implementación completa de la solución propuesta por Karussell. Vea mi respuesta a continuación.
Sam Shiles

1
@Karussell. Solo intenté configurar $ .ajax ({"caché": falso ...}). Esto no resuelve el problema de las solicitudes POST en iOS6. Presumiblemente porque JQuery según sus documentos supone que ningún navegador es lo suficientemente estúpido como para almacenar en caché las solicitudes de publicación. "Las páginas recuperadas con POST nunca se almacenan en caché, por lo que las opciones de caché e ifModified en jQuery.ajaxSetup () no tienen efecto en estas solicitudes".
Brett Hannah el

1
Esto no funciona No combina parámetros de publicación. La publicación de Dave es una mejor solución.
Chris Muench

43

Acabo de tener este problema también 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í unas horas resolviendo esto. Hubiera sido agradable de parte de Apple notificar a los desarrolladores sobre este problema de almacenamiento en caché.


1
Iba a comentar sobre el uso {cache:false}como una opción para cualquiera $.post()o $.ajaxSetup(), pero según los documentos , estos argumentos son ignorados; 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 usando $.ajaxPrefilter().
fwielstra

Paso casi 5 horas para solucionar este problema, y ​​finalmente agregar una marca de tiempo hará el truco function send_ajax(my_data,refresh) ... consulte aquí stackoverflow.com/questions/14733772/…
rusly

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);
    ...
}

2
¡Muchas gracias! Me estaba volviendo loco tratando de entender por qué el iPhone estaba actuando tan diferente a cualquier otra plataforma. Esta solución específica de ASP.NET me ahorró un montón de tiempo.
Mark Brittingham

No funcionó para iOS6, vea mi respuesta hacia el final del hilo
Brian Ogden

1
¡¡¡¡Por favor!!!! Ponga una condición para aplicar esto solo en IOS 6, el caché de contenido es vital para cualquier aplicación.
Alexandre

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

Desde mi propia publicación de blog, iOS 6.0, almacenamiento en caché de solicitudes POST de Ajax :

Cómo solucionarlo: existen varios métodos para evitar el almacenamiento en caché de las 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 enviar cualquier información al cliente.

.RED

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 buen atributo sin caché para .NET stackoverflow.com/questions/10011780/…
Aran Mulholland

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 cargar jQuery, y mejor antes de hacer 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 incorporada anti-caché 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 .)

Insertar 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 : "");
    }
}

A:

// 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 : "");
}

44
No es un buen enfoque para cambiar jQuery o, para el caso, cualquier código que no sea de su propiedad. (Cada vez que desee actualizar la versión, deberá realizar el cambio nuevamente. (O Otro desarrollador se actualiza y el programa no funciona))
andlrc

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 simplemente haciendo un cambio en un archivo.
Sam Shiles el

Puede verlo y jQuery.ajaxPrefilerle permite modificar su solicitud de ajax justo antes de hacerlo. Puede archivar lo mismo con un código seguro más optimizado y actualizado.
andlrc

1
El problema con el enfoque preFilter es que necesita registrar el filtro. Si tiene una secuencia de comandos común que se ejecuta cuando se carga cada página, entonces está bien, pero si no tiene que configurar el prefiltro para cada página que utiliza ajax. En el escenario que enfrenté, teníamos una ubicación común para el archivo JQ que se usaba 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 el

Luego, puede agregarlo nuevamente al final de ese archivo. Bien, lo resolvió, su empresa debe estar feliz por usted.
andlrc

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");

La mayoría de nosotros tenemos cientos de métodos remotos en sus implementaciones de GWT. ¿Existe una forma universal de configurar el encabezado de control de caché para todas las solicitudes?
Dirkoneill

5

Esta es una actualización de la respuesta de Baz1nga. Como options.datano es un objeto, sino una cadena, recurrí a la concatenación de 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
Agregar marcas de tiempo es una mala idea, prueba con la solución de Dave.
Nicholas Shanks

4

Para resolver este problema para las WebApps 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 las nuevas solicitudes se almacenen en caché en el futuro y se debe agregar alguna entrada aleatoria a cada solicitud de publicación para que las solicitudes que ya se hayan almacenado en caché puedan pasar. Por favor, consulte mi publicación:

iOS6: ¿hay alguna forma de borrar las solicitudes POST de ajax en caché para aplicaciones web agregadas a la pantalla de inicio?

ADVERTENCIA: a cualquiera que haya implementado una solución 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 posterior se almacenará en caché, al borrar el caché de safari no se borra y no parece que caduque. A menos que alguien tenga una manera de limpiarlo, ¡esto parece una posible pérdida de memoria!


¿Se almacenarán en caché todas las respuestas en el archivo o la memoria del teléfono?
Eydun

Este no fue el caso conmigo. Agregué una marca de tiempo a mi url (no parámetros de publicación) y funciona bien, tanto al navegar desde un safari como al guardar en la pantalla de inicio.
ShadeTreeDeveloper

4

Cosas que NO FUNCIONARON para mí 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);

¿Para qué es el voto negativo? Esta es una caché de información importante: falso no funciona con iPad4 / iOS6 ni //asp.net's: HttpContext.Current.Response.Cache.SetCacheability (HttpCacheability.NoCache)
Brian Ogden

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 será necesario agregar manualmente la marca de tiempo.
cowbert

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 alternativa en ASP.NET (métodos de página, servicio web, etc.)

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

1

Si bien agregar parámetros de cache-buster para hacer que la solicitud se vea diferente parece una solución sólida, desaconsejaría, 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 busters de caché a las personas que llaman.


1
Si bien estaría de acuerdo con usted en la mayoría de las circunstancias, argumentaría que la solución real a este problema es que Apple implemente correctamente HTTP. 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

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 basado en 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 compartir una idea sobre el almacenamiento en caché web.

Es cierto que puede agregar muchos encabezados en cada idioma que use, 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 puede saber desde dónde se conecta el cliente a su servidor, nunca se sabe si está utilizando una conexión "Hot-Spot" del hotel que utiliza Squid u otros productos de almacenamiento en caché.

Si los usuarios usan 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 utiliza.

Por ejemplo:

/ajax_helper.php?ts=3211321456

Luego, todos los administradores de caché que tienes que pasar no encontraron la misma URL en el repositorio de caché y volvieron a descargar el contenido de la página.


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 hace una $.ajaxy ha configurado las opciones para tenerla, {cache:false}entonces jQuery agregará automáticamente un bloqueo de caché detrás de escena sin que tengas que hacer nada más.
JakeGould

0

Dependiendo de la aplicación, puede solucionar el problema ahora en iOS 6 usando Safari> Avanzado> Inspector web, por lo que es útil con 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, incluidos los específicos de la aplicación mediante una Vista web. Solo una aplicación tuvo un problema y esto lo resolvió durante las pruebas beta de IOS6 hace mucho tiempo, desde entonces no hubo problemas reales.

Es posible que también necesite ver 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: llamadas $ .ajax


Si bien esto no aborda directamente la pregunta original, es una información muy útil para poder solucionar problemas en los dispositivos en general, por lo que estoy votando.
Kris Giesing

0

Encontré una solución alternativa 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 a checkStatus (). Por supuesto, me encontré con el problema de 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 como un encanto 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 volviendo nulo al onunloadevento, la página no se almacena en caché en Safari.


0

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

La solución es difícil de creer. Solo espera 1s y llama de nuevo. En nuestras pruebas, solo se necesitó una repetición, pero escribimos el código para llamar hasta 4 veces. No estamos seguros de si se requiere esperar 1s, pero no queríamos arriesgarnos a cargar nuestro servidor con ráfagas de llamadas repetidas.

Descubrimos que el problema ocurrió con dos llamadas AJAX diferentes, llamando a diferentes archivos API con datos diferentes. 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 todas las llamadas varias veces en dispositivos antiguos.

Ambas llamadas AJAX problemáticas 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 lo 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 dispositivos 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 principal resultado 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 así:

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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.