Depuis la mise à niveau vers iOS 6, nous voyons la vue Web de Safari prendre la liberté de mettre en cache les $.ajax
appels. C'est dans le contexte d'une application PhoneGap donc elle utilise Safari WebView. Nos $.ajax
appels sont des POST
méthodes et nous avons mis le cache sur false {cache:false}
, mais cela se produit toujours. Nous avons essayé d'ajouter manuellement un TimeStamp
en-tête mais cela n'a pas aidé.
Nous avons fait plus de recherches et avons découvert que Safari ne renvoie que les résultats mis en cache pour les services Web qui ont une signature de fonction qui est statique et ne change pas d'un appel à l'autre. Par exemple, imaginez une fonction appelée quelque chose comme:
getNewRecordID(intRecordType)
Cette fonction reçoit les mêmes paramètres d'entrée encore et encore, mais les données qu'elle renvoie doivent être différentes à chaque fois.
Doit être dans la hâte d'Apple pour que iOS 6 avance de manière impressionnante, ils sont trop satisfaits des paramètres de cache. Quelqu'un d'autre a-t-il vu ce comportement sur iOS 6? Si oui, quelle en est exactement la cause?
La solution de contournement que nous avons trouvée consistait à modifier la signature de la fonction pour qu'elle ressemble à ceci:
getNewRecordID(intRecordType, strTimestamp)
puis passez toujours un TimeStamp
paramètre également, et jetez simplement cette valeur du côté serveur. Cela fonctionne autour du problème. J'espère que cela aide une autre pauvre âme qui passe 15 heures sur cette question comme moi!
la source
Réponses:
Après un peu d'investigation, il s'avère que Safari sur iOS6 mettra en cache les POST qui n'ont aucun en-tête Cache-Control ou même "Cache-Control: max-age = 0".
La seule façon que j'ai trouvée d'empêcher cette mise en cache de se produire au niveau global plutôt que d'avoir à pirater des chaînes de requête aléatoires sur les appels de fin de service est de définir "Cache-Control: no-cache".
Donc:
Je soupçonne qu'Apple profite de cela à partir de la spécification HTTP dans la section 9.5 sur POST:
Donc, en théorie, vous pouvez mettre en cache les réponses POST ... qui savait. Mais aucun autre fabricant de navigateur n'a jamais pensé que ce serait une bonne idée jusqu'à présent. Mais cela ne tient PAS compte de la mise en cache lorsqu'aucun en-tête Cache-Control ou Expires n'est défini, uniquement lorsqu'il y en a. Donc ça doit être un bug.
Vous trouverez ci-dessous ce que j'utilise dans la partie droite de ma configuration Apache pour cibler l'ensemble de mon API car, en l'occurrence, je ne veux vraiment rien mettre en cache, même le obtient. Ce que je ne sais pas, c'est comment régler cela juste pour les POST.
Mise à jour: Je viens de remarquer que je n'ai pas souligné que ce n'est que lorsque le POST est le même, alors changez les données ou l'URL du POST et tout va bien. Vous pouvez donc, comme mentionné ailleurs, simplement ajouter des données aléatoires à l'URL ou un peu de données POST.
Mise à jour: vous pouvez limiter le "no-cache" uniquement aux POST si vous le souhaitez dans Apache:
la source
J'espère que cela pourra être utile à d'autres développeurs se cognant la tête contre le mur de celui-ci. J'ai constaté que l'un des éléments suivants empêche Safari sur iOS 6 de mettre en cache la réponse POST:
Ma solution était la suivante dans mon Javascript (toutes mes demandes AJAX sont POST).
J'ajoute également l'en-tête [pragma: no-cache] à plusieurs de mes réponses de serveur.
Si vous utilisez la solution ci-dessus, sachez que tous les appels $ .ajax () que vous effectuez et qui sont définis sur global: false n'utiliseront PAS les paramètres spécifiés dans $ .ajaxSetup (), vous devrez donc ajouter à nouveau les en-têtes.
la source
Solution simple pour toutes vos demandes de service Web, en supposant que vous utilisez jQuery:
En savoir plus sur l'appel du préfiltre jQuery ici .
Si vous n'utilisez pas jQuery, consultez les documents de votre bibliothèque de choix. Ils peuvent avoir des fonctionnalités similaires.
la source
Je viens d'avoir ce problème également dans une application PhoneGap . Je l'ai résolu en utilisant la fonction JavaScript
getTime()
de la manière suivante:J'ai perdu quelques heures à comprendre cela. Il aurait été agréable qu'Apple informe les développeurs de ce problème de mise en cache.
la source
{cache:false}
en option de l'un$.post()
ou de l' autre$.ajaxSetup()
, mais selon les documents , ces arguments sont ignorés; jQuery ne mettra jamais en cache les demandes de publication, mais ne tient pas compte du navigateur. Une option plus soignée serait peut-être d'ajouter un horodatage aux requêtes utilisant$.ajaxPrefilter()
.function send_ajax(my_data,refresh)
. reportez-vous ici stackoverflow.com/questions/14733772/…J'ai eu le même problème avec une application Web obtenant des données du service Web ASP.NET
Cela a fonctionné pour moi:
la source
Enfin, j'ai une solution à mon problème de téléchargement.
En JavaScript:
En PHP :
la source
De mon propre article de blog iOS 6.0 mettant en cache les requêtes Ajax POST :
Comment résoudre ce problème: Il existe différentes méthodes pour empêcher la mise en cache des demandes. La méthode recommandée consiste à ajouter un en-tête sans cache. Voilà comment cela se fait.
jQuery:
Vérifiez iOS 6.0 et définissez l'en-tête Ajax comme ceci:
ZeptoJS:
Vérifiez iOS 6.0 et définissez l'en-tête Ajax comme ceci:
Du côté serveur
Java:
Assurez-vous d'ajouter ceci en haut de la page avant d'envoyer des données au client.
.NET
Ou
PHP
la source
Cet extrait JavaScript fonctionne parfaitement avec jQuery et jQuery Mobile:
Il suffit de le placer quelque part dans votre code JavaScript (après le chargement de jQuery, et mieux avant de faire des requêtes AJAX) et cela devrait vous aider.
la source
Vous pouvez également résoudre ce problème en modifiant jQuery Ajax fonction en procédant comme suit (à partir de 1.7.1) en haut de la fonction Ajax (la fonction commence à la ligne 7212). Cette modification activera la fonction anti-cache intégrée de jQuery pour toutes les requêtes POST.
(Le script complet est disponible sur
http://dl.dropbox.com/u/58016866/jquery-1.7.1.js
.)Insérez sous la ligne 7221:
Modifiez ensuite ce qui suit (à partir de la ligne ~ 7497).
À:
la source
jQuery.ajaxPrefiler
vous permet de modifier votre demande ajax juste avant de la faire. Vous pouvez les archiver avec un code plus optimisé et plus sûr.Une solution rapide pour les services GWT-RPC consiste à ajouter ceci à toutes les méthodes distantes:
la source
Ceci est une mise à jour de la réponse de Baz1nga. Puisque ce
options.data
n'est pas un objet mais une chaîne, je viens de recourir à la concaténation de l'horodatage:la source
Afin de résoudre ce problème pour les applications Web ajoutées à l'écran d'accueil, les deux solutions de contournement les plus votées doivent être suivies. La mise en cache doit être désactivée sur le serveur Web pour empêcher la mise en cache de nouvelles demandes et certaines entrées aléatoires doivent être ajoutées à chaque demande de publication pour que les demandes qui ont déjà été mises en cache soient traitées. Veuillez vous référer à mon message:
iOS6 - Existe-t-il un moyen d'effacer les demandes POST ajax mises en cache pour une application Web ajoutée à l'écran d'accueil?
AVERTISSEMENT: à toute personne ayant implémenté une solution de contournement en ajoutant un horodatage à ses demandes sans désactiver la mise en cache sur le serveur. Si votre application est ajoutée à l'écran d'accueil, CHAQUE réponse sera désormais mise en cache, l'effacement du cache safari ne l'efface pas et il ne semble pas expirer. À moins que quelqu'un ait un moyen de l'effacer, cela ressemble à une fuite de mémoire potentielle!
la source
Choses qui n'ont pas fonctionné pour moi avec un iPad 4 / iOS 6:
Ma demande contenant: Cache-Control: no-cache
Ajout de cache: faux à mon appel ajQuery jQuery
Seulement cela a fait l'affaire:
la source
$.ajax
cache: false
ajoute l'URL avec le paramètre de requête_=Date.prototype.getTime()
, donc l'ajout manuel de l'horodatage ne devrait plus être nécessaire.Voilà le travail autour de GWT-RPC
la source
Ma solution de contournement dans ASP.NET (pagemethods, webservice, etc.)
la source
Bien que l'ajout de paramètres de cache-buster pour rendre la demande différente semble être une solution solide, je déconseille cela, car cela nuirait à toute application qui repose sur la mise en cache réelle. Faire en sorte que les API produisent les en-têtes corrects est la meilleure solution possible, même si c'est un peu plus difficile que d'ajouter des cache-cache aux appelants.
la source
Pour ceux qui utilisent
Struts 1
, voici comment j'ai résolu le problème.web.xml
com.example.struts.filters.CacheControlFilter.js
la source
J'ai pu résoudre mon problème en utilisant une combinaison de $ .ajaxSetup et en ajoutant un horodatage à l'url de mon message (pas aux paramètres / corps du message). Ceci basé sur les recommandations des réponses précédentes
la source
Je pense que vous avez déjà résolu votre problème, mais permettez-moi de partager une idée sur la mise en cache Web.
Il est vrai que vous pouvez ajouter de nombreux en-têtes dans chaque langue que vous utilisez, côté serveur, côté client, et vous pouvez utiliser de nombreuses autres astuces pour éviter la mise en cache Web, mais pensez toujours que vous ne pouvez jamais savoir d'où le client se connecte à votre serveur, vous ne savez jamais s'il utilise une connexion «Hot-Spot» d'hôtel qui utilise Squid ou d'autres produits de mise en cache.
Si les utilisateurs utilisent un proxy pour cacher sa position réelle, etc… le seul moyen réel d'éviter la mise en cache est l'horodatage de la demande également s'il n'est pas utilisé.
Par exemple:
Ensuite, chaque gestionnaire de cache que vous devez passer n'a pas trouvé la même URL dans le référentiel de cache et a téléchargé à nouveau le contenu de la page.
la source
$.ajax
et avez défini les options pour avoir,{cache:false}
jQuery lui-même ajoutera automatiquement un contournement du cache dans les coulisses sans que vous ayez besoin de faire autre chose.Selon l'application, vous pouvez résoudre le problème maintenant dans iOS 6 en utilisant Safari> Avancé> Inspecteur Web, ce qui est utile dans cette situation.
Connectez le téléphone à Safari sur un Mac et utilisez le menu développeur pour résoudre les problèmes liés à l'application Web.
Effacez les données du site Web sur l'iPhone après la mise à jour vers iOS6, y compris celles spécifiques à l'application à l'aide d'une vue Web. Une seule application a eu un problème et cela l'a résolu lors du test de la version bêta d'IOS6, depuis lors, aucun problème réel.
Vous devrez peut-être également consulter votre application, consultez NSURLCache si dans une WebView dans une application personnalisée.
https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSURLCache_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40003754
Je suppose que cela dépend de la vraie nature de votre problème, de sa mise en œuvre, etc.
Ref: Appels $ .ajax
la source
J'ai trouvé une solution de contournement qui me rend curieux de savoir pourquoi cela fonctionne. Avant de lire la réponse de Tadej concernant le service Web ASP.NET, j'essayais de trouver quelque chose qui fonctionnerait.
Et je ne dis pas que c'est une bonne solution, mais je voulais juste la documenter ici.
page principale: inclut une fonction JavaScript, checkStatus (). La méthode appelle une autre méthode qui utilise un appel jQuery AJAX pour mettre à jour le contenu html. J'ai utilisé setInterval pour appeler checkStatus (). Bien sûr, j'ai rencontré le problème de la mise en cache.
Solution: utilisez une autre page pour appeler la mise à jour.
Sur la page principale, j'ai défini une variable booléenne, runUpdate, et ajouté ce qui suit à la balise body:
Dans le fichier helper.html:
Donc, si checkStatus () est appelé depuis la page principale, j'obtiens le contenu mis en cache. Si j'appelle checkStatus depuis la page enfant, j'obtiens un contenu mis à jour.
la source
Alors que mes pages de connexion et d'inscription fonctionnent comme un charme dans Firefox, IE et Chrome ... J'ai eu du mal avec ce problème dans Safari pour IOS et OSX, il y a quelques mois, j'ai trouvé une solution de contournement sur le SO.
OU via javascript
C'est un peu moche mais ça marche pendant un moment.
Je ne sais pas pourquoi, mais en renvoyant null à l'
onunload
événement, la page n'est pas mise en cache dans Safari.la source
Nous avons constaté que les iPhones et iPads plus anciens, exécutant les versions iOS 9 et 10, retournent parfois de faux résultats AJAX vides, peut-être en raison de la baisse de la vitesse du processeur d'Apple. Lors du retour du résultat vide, iOS n'appelle pas le serveur, comme s'il renvoyait un résultat du cache. La fréquence varie considérablement, d'environ 10% à 30% des appels AJAX retournant en blanc.
La solution est difficile à croire. Attendez 1 seconde et appelez à nouveau. Lors de nos tests, une seule répétition a suffi, mais nous avons écrit le code pour appeler jusqu'à 4 fois. Nous ne savons pas si l'attente 1s est requise, mais nous ne voulions pas risquer de surcharger notre serveur avec des rafales d'appels répétés.
Nous avons constaté que le problème était survenu avec deux appels AJAX différents, appelant des fichiers API différents avec des données différentes. Mais je crains que cela ne se produise sur n'importe quel appel AJAX. Nous ne le savons tout simplement pas, car nous n'inspectons pas tous les résultats AJAX et nous ne testons pas chaque appel plusieurs fois sur d'anciens appareils.
Les deux appels AJAX problématiques utilisaient: POST, asynchrone = true, setRequestHeader = ('Content-Type', 'application / x-www-form-urlencoded')
Lorsque le problème se produit, il n'y a généralement qu'un seul appel AJAX en cours. Ce n'est donc pas dû au chevauchement des appels AJAX. Parfois, le problème se produit lorsque l'appareil est occupé, mais parfois non, et sans DevTools, nous ne savons pas vraiment ce qui se passe à ce moment-là.
iOS 13 ne le fait pas, ni Chrome ni Firefox. Nous n'avons pas d'appareils de test fonctionnant sous iOS 11 ou 12. Peut-être que quelqu'un d'autre pourrait les tester?
Je note cela ici, car cette question est le meilleur résultat Google lors de la recherche de ce problème.
la source
Cela n'a fonctionné avec ASP.NET qu'après avoir ajouté l'en-
pragma:no-cache
tête dans IIS .Cache-Control: no-cache
n'était pas suffisant.la source
Je suggère une solution de contournement pour modifier la signature de la fonction pour qu'elle ressemble à ceci:
getNewRecordID (intRecordType, strTimestamp), puis passez également un paramètre TimeStamp également, et jetez simplement cette valeur du côté serveur. Cela fonctionne autour du problème.
la source