Empêcher la mise en cache par le navigateur du résultat de l'appel AJAX

262

Il semble que si je charge du contenu dynamique à l'aide $.get(), le résultat est mis en cache dans le navigateur.

L'ajout d'une chaîne aléatoire dans QueryString semble résoudre ce problème (j'utilise new Date().toString()), mais cela ressemble à un hack.

Existe-t-il un autre moyen d'y parvenir? Ou, si une chaîne unique est le seul moyen d'y parvenir, des suggestions autres que new Date()?

Salamandre2007
la source
Vous pouvez utiliser la notation courte $.now()au lieu de faire (new Date (). GetTime ()) à chaque fois.
Dayson
1
Le titre de votre question est un peu trompeur. Pourriez-vous envisager de le renommer?
0112
4
Avez-vous envisagé de sélectionner une autre réponse comme étant la réponse acceptée?
M4N

Réponses:

241

J'utilise new Date().getTime(), ce qui évitera les collisions à moins que vous ayez plusieurs demandes se produisant dans la même milliseconde:

$.get('/getdata?_=' + new Date().getTime(), function(data) {
    console.log(data); 
});

Edit: Cette réponse a plusieurs années. Cela fonctionne toujours (donc je ne l'ai pas supprimé), mais il existe maintenant des moyens meilleurs / plus propres d'y parvenir . Ma préférence va à cette méthode, mais cette réponse est également utile si vous souhaitez désactiver la mise en cache pour chaque demande pendant la durée de vie d'une page.

Mark Bell
la source
11
Je ne voterai que parce qu'il est plus propre de laisser jQuery faire cela comme dans la réponse de Peter J. Votre solution fonctionnera, mais est plus difficile à maintenir à long terme.
Niklas Wulff
11
Quelle partie de cela nécessite une maintenance? Par rapport à ce que jQuery fait?
Sunny R Gupta
5
Il est intéressant de noter que le new Date().getTime()code est utilisé comme ça ... var nocache = new Date().getTime(); var path = 'http://hostname.domain.tld/api/somejsonapi/?cache=' + nocache;. Il m'a fallu quelques minutes pour comprendre celui-là, moi-même. Bien sûr, il ?cachepourrait s'agir d'une formulation que l'API ne souhaite pas réellement.
doubleJ
1
+1 même la réponse de Peter J ayant une meilleure approche, cette réponse n'est pas fausse ni mauvaise. Je crois que les DV sont faits parce que le vôtre est au-dessus de celui de Peter (comme accepté). et l'OP n'apparaît pas sur SO depuis début 2013
Michel Ayres
1
url = url + (-1 === url.indexOf('?') ? '?' : '&') + "__=" + Number(new Date());
514

Les éléments suivants empêcheront toutes les futures demandes AJAX d'être mises en cache, quelle que soit la méthode jQuery que vous utilisez ($ .get, $ .ajax, etc.)

$.ajaxSetup({ cache: false });
Peter J
la source
7
Après enquête (Fiddler), il semble que jQuery implémente cela en interne en ajoutant simplement un horodatage de toute façon (comme discuté ailleurs dans ces réponses). Pour moi, la méthode .ajaxSetup est plus propre (à mon avis.)
Peter J
8
En effet, il n'a pas besoin d'être à l'intérieur de l'appel de document prêt.
Peter J
19
Pourquoi désactiver la mise en cache ajax globalement? Je pense que cela devrait être fait par appel, comme ce que fait la réponse de Jonathan.
Sunny R Gupta
5
Tout ce qui fonctionne pour votre application. Je continue d'utiliser cette méthode dans les applications commerciales chaque fois que j'ai absolument besoin de nouvelles données pour tous les appels AJAX. Pour d'autres, les données mises en cache conviennent.
Peter J
1
lien Description: Définissez les valeurs par défaut pour les futures demandes Ajax. Son utilisation n'est pas recommandée.
itwebdeveloper
319

$ .Get () de JQuery mettra en cache les résultats. Au lieu de

$.get("myurl", myCallback)

vous devez utiliser $ .ajax, qui vous permettra de désactiver la mise en cache:

$.ajax({url: "myurl", success: myCallback, cache: false});
Jonathan Moffatt
la source
62
+1 C'est la bonne réponse. La solution de Peter J consistant à désactiver globalement la mise en cache est une mauvaise pratique de l'OMI.
Salman von Abbas
7
Il est important de noter que ce n'est que "global" pour la page / demande.
Peter J
3
+1: la mise en cache doit être spécifique au type de demande. Certaines demandes de serveur peuvent nécessiter une mise en cache (lorsque les données du serveur sont statiques), il est donc préférable de choisir la mise en cache demande par demande plutôt que de tout désactiver .
Fin du codage du
1
+1 pour une réponse correcte - empêchant la mise en cache par appel en utilisant la méthode de jQuery, plutôt qu'un hack manuel.
Brendan Hill
2
Une autre bonne réponse. Je dois dire que pour moi, la plupart du temps, la désactivation globale du cache a été très bénéfique. Tout dépend de la façon dont votre application est conçue. Il n'y a pas de solution miracle, mais dans cette situation, je recommanderais une fonction qui accepte un booléen pour la mise en cache, une fonction pour le rappel et une URL pour la modularité. Le "hack" manuel est très bien, mais si vous utilisez jQuery, respectez leurs fonctions autant que possible. Cela facilitera non seulement le développement maintenant, mais également les futures mises à niveau de la bibliothèque.
Anthony Mason
24

Toutes les réponses ici laissent une empreinte sur l'URL demandée qui apparaîtra dans les journaux d'accès du serveur.

J'avais besoin d'une solution basée sur les en-têtes sans effet secondaire et j'ai trouvé qu'elle pouvait être obtenue en configurant les en-têtes mentionnés dans Comment contrôler la mise en cache des pages Web, sur tous les navigateurs? .

Le résultat, fonctionnant pour Chrome au moins, serait:

$.ajax({
   url: url, 
   headers: {
     'Cache-Control': 'no-cache, no-store, must-revalidate', 
     'Pragma': 'no-cache', 
     'Expires': '0'
   }
});

Aide à
la source
Peut-être une question stupide, mais si mon ajax renvoie des images, les images seront-elles mises en cache? Pour éviter les demandes massives d'Amazon S3?
Marcelo Agimóvel
MarceloAgimóvel, cela peut être une question distincte de SO, je crois.
Aidin
23

une autre façon consiste à ne fournir aucun en-tête de cache à partir du côté serveur dans le code qui génère la réponse à l'appel ajax:

response.setHeader( "Pragma", "no-cache" );
response.setHeader( "Cache-Control", "no-cache" );
response.setDateHeader( "Expires", 0 );
miceuz
la source
17
Incorrect. Dans IE, les en-têtes sans cache sont ignorés pour les appels XMLHttpRequest, comme indiqué ici: stackoverflow.com/questions/244918/… Le DateTime (ou ma méthode .ajaxSetup) sont les seules solutions qui fonctionnent réellement.
Peter J
je viens de coller mon mantra habituel sans cache, il n'est pas dit qu'il est spécifique à IE
miceuz
2
Cela devrait désactiver la mise en cache pour tous les navigateurs: response.setHeader ("Cache-Control", "max-age = 0, no-cache, no-store, post-check = 0, pre-check = 0");
Chris Broski
13

Personnellement, je pense que la méthode de la chaîne de requête est plus fiable que d'essayer de définir des en-têtes sur le serveur - il n'y a aucune garantie qu'un proxy ou un navigateur ne le mettra pas en cache de toute façon (certains navigateurs sont pires que d'autres - ne nommer aucun nom).

J'utilise habituellement Math.random()mais je ne vois rien de mal à utiliser la date (vous ne devriez pas faire de requêtes AJAX assez rapidement pour obtenir deux fois la même valeur).

Greg
la source
2
Combinez Date (). GetTime () avec Math.random () et vous devriez être du bon côté. Sur une note latérale, Ext.Ajax utilise également getTime () lorsque disableCaching est spécifié.
vividos
12

Suite à la documentation: http://api.jquery.com/jquery.ajax/

vous pouvez utiliser la cachepropriété avec:

$.ajax({
    method: "GET",
    url: "/Home/AddProduct?",
    data: { param1: value1, param2: value2},
    cache: false,
    success: function (result) {
        // TODO
    }
});
MrMins
la source
5

Bien sûr, les techniques de "rupture de cache" feront le travail, mais cela ne se produira pas en premier lieu si le serveur indique au client que la réponse ne doit pas être mise en cache. Dans certains cas, il est avantageux de mettre en cache les réponses, parfois non. Laissez le serveur décider de la durée de vie correcte des données. Vous voudrez peut-être le changer plus tard. Beaucoup plus facile à faire à partir du serveur qu'à partir de nombreux endroits différents dans votre code d'interface utilisateur.

Bien sûr, cela n'aide pas si vous n'avez aucun contrôle sur le serveur.

Mark Renouf
la source
5

Qu'en est-il de l'utilisation d'une demande POST au lieu d'un GET ...? (Ce que vous devriez quand même ...)

Thomas Hansen
la source
Je pense que c'est une meilleure solution, mais malheureusement, je ne peux (en quelque sorte) que faire une demande GET. Donc ... c'est nouveau Date (). GetTime () pour l'instant.
Salamander2007
Veuillez ajouter quelques explications à votre réponse afin que d'autres puissent en tirer des leçons - pourquoi une demande POST devrait-elle être nécessaire?
Nico Haase
5

La vraie question est pourquoi vous avez besoin que cela ne soit pas mis en cache. S'il ne doit pas être mis en cache car il change tout le temps, le serveur doit spécifier de ne pas mettre en cache la ressource. S'il change simplement parfois (car l'une des ressources dont il dépend peut changer), et si le code client a un moyen de le savoir, il peut ajouter un paramètre factice à l'URL qui est calculé à partir d'un hachage ou d'une date de dernière modification de ces ressources (c'est ce que nous faisons dans les ressources de script Microsoft Ajax afin qu'elles puissent être mises en cache pour toujours mais les nouvelles versions peuvent toujours être servies telles qu'elles apparaissent). Si le client ne peut pas connaître les modifications, la manière correcte devrait être que le serveur gère correctement les requêtes HEAD et indique au client s'il doit utiliser la version mise en cache ou non. Il me semble que l'ajout d'un paramètre aléatoire ou le fait de dire au client de ne jamais mettre en cache est incorrect car la mise en cache est une propriété de la ressource serveur, et doit donc être décidée côté serveur. Une autre question à se poser est de savoir si cette ressource doit vraiment être servie via GET ou doit-elle passer par POST? C'est une question de sémantique, mais cela a aussi des implications de sécurité (il y a des attaques qui ne fonctionnent que si le serveur autorise GET). POST ne sera pas mis en cache.


la source
6
Que faire si vous passez par des serveurs proxy dont vous ne contrôlez pas la politique de mise en cache? que faire si votre application doit explicitement faire une nouvelle demande à chaque fois? La réponse aux choses n'est pas toujours claire en noir et blanc, il y a toujours des zones grises.
7wp
Certes, ce n'est pas toujours clair. Mais voir cette réponse m'a fait remettre en question mes hypothèses et m'a amené à trouver la cause profonde de mon problème. Ce n'est peut-être pas le cas pour tout le monde, mais cela m'a aidé. Si vous lisez ici ceci, vous devriez également le considérer.
Jonathan Tran
Cela m'a aidé, ResponseCaching a été défini sur 60 m côté serveur par défaut. Changé en No-Cache et il a arrêté la mise en cache sur le client.
mattygee
4

Vous devriez peut-être plutôt regarder $ .ajax () (si vous utilisez jQuery, à quoi il ressemble). Jetez un œil à: http://docs.jquery.com/Ajax/jQuery.ajax#options et l'option "cache".

Une autre approche consisterait à regarder comment vous cachez les choses côté serveur.

finpingvin
la source
1
Malheureusement, après quelques recherches, l'utilisation de $ .ajax () et set cache = false fera essentiellement la même chose. jQuery ajoutera un nombre aléatoire à la chaîne de requête et ne vérifie pas la chaîne de requête existante. Donc je suppose que l'utilisation de $ .get () suffira.
Salamander2007
Ah d'accord. Je ne l'ai jamais essayé, je me souviens juste que j'avais vu quelque chose à ce sujet dans les documents :)
finpingvin
Il n'est même pas nécessaire d'utiliser $ .ajax. Utilisez simplement .ajaxSetup.
Peter J
3

Un petit ajout aux excellentes réponses données: si vous utilisez une solution de sauvegarde non ajax pour les utilisateurs sans javascript, vous devrez quand même corriger ces en-têtes côté serveur. Ce n'est pas impossible, même si je comprends ceux qui y renoncent;)

Je suis sûr qu'il y a une autre question sur SO qui vous donnera l'ensemble complet des en-têtes appropriés. Je ne suis pas entièrement convaincu miceus réponse couvre toutes les bases à 100%.

krosenvold
la source
3

Pour ceux d'entre vous qui utilisent l' cacheoption de $.ajaxSetup()Safari mobile, il semble que vous devrez peut-être utiliser un horodatage pour les POST, car Safari mobile le met également en cache. Selon la documentation sur $.ajax()(vers laquelle vous êtes dirigé $.ajaxSetup()):

Définir le cache sur false ne fonctionnera correctement qu'avec les requêtes HEAD et GET. Il fonctionne en ajoutant "_ = {timestamp}" aux paramètres GET. Le paramètre n'est pas nécessaire pour d'autres types de demandes, sauf dans IE8 lorsqu'un POST est effectué sur une URL qui a déjà été demandée par un GET.

Donc, définir cette option ne vous aidera pas dans le cas que j'ai mentionné ci-dessus.

Athasach
la source
2

Fondamentalement, ajoutez simplement cache:false;l'ajax où vous pensez que le contenu changera au fur et à mesure de la progression. Et l'endroit où le contenu ne changera pas là, vous pouvez l'omettre. De cette façon, vous obtiendrez la nouvelle réponse à chaque fois

Santosh Upadhayay
la source
2

Maintenant, il est facile de le faire en activant / désactivant l'option de cache dans votre demande ajax, comme ceci

$(function () {
    var url = 'your url goes here';
    $('#ajaxButton').click(function (e) {
        $.ajax({
            url: url,
            data: {
                test: 'value'
            },
                cache: true, //cache enabled, false to reverse
                complete: doSomething
            });
        });
    });
    //ToDo after ajax call finishes
    function doSomething(data) {
        console.log(data);
    }
});
Omar El Don
la source
3
Après 6 ans, vous fournissez la même réponse que Jonathan? ಠ_ಠ
redent84
les gens peuvent dire que c'est 6 ans après la publication de la question. Et ma réponse à cette question est différente de toute autre, sans compter que c'est la bonne aujourd'hui. Répondre à de telles questions n'est pas pour le "demandeur", c'est pour la communauté et les débutants! Merci d'avoir ajouté la clarification de toute façon!
Omar El Don
Et quelle est la différence entre la vôtre et celle-ci stackoverflow.com/a/735084/469218 ?
redent84
c'est peut-être de la clarté, du point de vue d'un débutant posant une telle question !!
Omar El Don
1

Comme @Athasach l'a dit, selon les documents jQuery, $.ajaxSetup({cache:false})ne fonctionnera pas pour les requêtes GET et HEAD.

Vous feriez mieux de renvoyer un en- Cache-Control: no-cachetête de votre serveur de toute façon. Il offre une séparation plus nette des préoccupations.

Bien sûr, cela ne fonctionnerait pas pour les URL de service auxquelles vous n'appartenez pas à votre projet. Dans ce cas, vous pouvez envisager de mandater le service tiers à partir du code serveur plutôt que de l'appeler à partir du code client.

rstackhouse
la source
1

Si vous utilisez .net ASP MVC, désactivez la mise en cache sur l'action du contrôleur en ajoutant l'attribut suivant sur la fonction de point de terminaison:

[OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
Marius
la source
Pouvez-vous expliquer cela davantage? Comment ce tableau est-il lié à AJAX?
Nico Haase
Ce n'est pas un tableau, c'est un attribut sur une action de contrôleur MVC.
Marius
0

ajouter un en-tête

headers: {
                'Cache-Control':'no-cache'
            }
Moaz Salem
la source
Veuillez ajouter quelques explications à votre réponse afin que d'autres puissent en tirer des enseignements - ces en-têtes doivent-ils être ajoutés?
Nico Haase
-3

ajouter Math.random() à l'url de la demande

xiaoyifang
la source
2
Cela donnera des résultats instables.
aj.toulan
Math.random agira uniquement comme un paramètre, comme url? _ = [Math.Random ()], cela n'a rien à voir avec un résultat instable.
xiaoyifang
4
Je comprends ce que tu faisais. Je commentais simplement que Math.Random () vous donnera parfois le même numéro deux fois. Si vous remplissez votre système d'incertitudes, ils s'ajouteront les uns aux autres.
aj.toulan