Desde la actualización a iOS 6, estamos viendo que la vista web de Safari se toma la libertad de almacenar en caché las $.ajax
llamadas. Esto está en el contexto de una aplicación PhoneGap, por lo que está utilizando Safari WebView. Nuestras $.ajax
llamadas son POST
métodos y tenemos el caché establecido en falso {cache:false}
, pero aún así esto está sucediendo. Intentamos agregar manualmente TimeStamp
a 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 TimeStamp
pará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!
fuente
Respuestas:
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:
Sospecho que Apple se está aprovechando de esto desde la especificación HTTP en la sección 9.5 sobre POST:
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.
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:
fuente
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:
Mi solución fue la siguiente en mi Javascript (todas mis solicitudes de AJAX son POST).
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.
fuente
Solución simple para todas sus solicitudes de servicio web, suponiendo que esté utilizando jQuery:
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.
fuente
Acabo de tener este problema también en una aplicación PhoneGap . Lo resolví usando la función JavaScript
getTime()
de la siguiente manera:Perdí unas horas resolviendo esto. Hubiera sido agradable de parte de Apple notificar a los desarrolladores sobre este problema de almacenamiento en caché.
fuente
{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()
.function send_ajax(my_data,refresh)
... consulte aquí stackoverflow.com/questions/14733772/…Tuve el mismo problema con una aplicación web que obtenía datos del servicio web ASP.NET
Esto funcionó para mí:
fuente
Finalmente, tengo una solución a mi problema de carga.
En JavaScript:
En PHP :
fuente
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:
ZeptoJS:
Verifique iOS 6.0 y configure el encabezado Ajax de esta manera:
Lado del servidor
Java:
Asegúrese de agregar esto en la parte superior de la página antes de enviar cualquier información al cliente.
.RED
O
PHP
fuente
Este fragmento de JavaScript funciona muy bien con jQuery y jQuery Mobile:
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.
fuente
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:
Luego modifique lo siguiente (comenzando en la línea ~ 7497).
A:
fuente
jQuery.ajaxPrefiler
le permite modificar su solicitud de ajax justo antes de hacerlo. Puede archivar lo mismo con un código seguro más optimizado y actualizado.Una solución rápida para los servicios GWT-RPC es agregar esto a todos los métodos remotos:
fuente
Esta es una actualización de la respuesta de Baz1nga. Como
options.data
no es un objeto, sino una cadena, recurrí a la concatenación de la marca de tiempo:fuente
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!
fuente
Cosas que NO FUNCIONARON para mí con un iPad 4 / iOS 6:
Mi solicitud contiene: Cache-Control: no-cache
Agregar caché: falso a mi llamada jQuery ajax
Solo esto hizo el truco:
fuente
$.ajax
cache: false
agrega la url con el parámetro de consulta_=Date.prototype.getTime()
, por lo que ya no será necesario agregar manualmente la marca de tiempo.Esa es la solución para GWT-RPC
fuente
Mi solución alternativa en ASP.NET (métodos de página, servicio web, etc.)
fuente
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.
fuente
Para aquellos que usan
Struts 1
, así es como solucioné el problema.web.xml
com.example.struts.filters.CacheControlFilter.js
fuente
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
fuente
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:
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.
fuente
$.ajax
y 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.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
fuente
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:
En el de helper.html:
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.
fuente
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.
O a través de javascript
Esto es algo feo pero funciona por un tiempo.
No sé por qué, pero volviendo nulo al
onunload
evento, la página no se almacena en caché en Safari.fuente
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.
fuente
Funcionó con ASP.NET solo después de agregar el
pragma:no-cache
encabezado en IIS .Cache-Control: no-cache
no fue suficiente.fuente
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.
fuente