web-dev-qa-db-fra.com

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

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

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

Y a-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()?

245
Salamander2007

J'utilise new Date().getTime(), ce qui évitera les collisions à moins que plusieurs requêtes ne se produisent 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 des moyens meilleurs/plus propres de réaliser cela maintenant . Ma préférence va à la méthode this , mais la réponse this est également utile si vous souhaitez désactiver la mise en cache pour chaque requête au cours de la durée de vie d'une page.

229
Mark Bell

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

$.ajaxSetup({ cache: false });
505
Peter J

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

$.get("myurl", myCallback)

vous devriez utiliser $ .ajax, ce qui vous permettra de désactiver le cache:

$.ajax({url: "myurl", success: myCallback, cache: false});
300
Jonathan Moffatt

une autre solution consiste à ne fournir aucun en-tête de cache 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 );
23
miceuz

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é que cela pouvait être réalisé 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'
   }
});
21
Aidin

Personnellement, j'estime 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 - rien ne garantit qu'un proxy ou un navigateur ne le mettra pas en cache de toute façon (certains navigateurs sont pires que d'autres - ne nommant aucun nom).

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

13
Greg

Après la documentation: http://api.jquery.com/jquery.ajax/

vous pouvez utiliser la propriété cache avec:

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

Bien sûr, les techniques de "suppression du cache" feront le travail, mais cela ne se produira pas 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 pas. 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 depuis le serveur que depuis de nombreux endroits différents dans votre code d'interface utilisateur.

Bien sûr, cela n’aide en rien si vous n’avez aucun contrôle sur le serveur.

5
Mark Renouf

Qu'en est-il de l'utilisation d'une demande POST au lieu d'un GET ...? (Ce que vous devriez de toute façon ...)

5
Thomas Hansen

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

Une autre approche consisterait à examiner comment mettre en cache des éléments côté serveur.

4
finpingvin

Un petit ajout aux excellentes réponses fournies: 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, bien que je comprenne ceux qui l'abandonnent;)

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

3
krosenvold

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

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

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

3
Athasach

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);
    }
});
2
Omar El Don

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

2
Santosh Upadhayay

Ajax Caching d’Internet Explorer: Qu'allez-vous faire à ce sujet? suggère trois approches:

  1. Ajoutez un jeton de contournement du cache à la chaîne de requête, par exemple? Date = [timestamp]. Dans jQuery et YUI, vous pouvez leur dire de le faire automatiquement.
  2. Utilisez POST au lieu d'un GET
  3. Envoyer un en-tête de réponse HTTP qui interdit spécifiquement aux navigateurs de le mettre en cache
2
Lijo

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

Vous feriez mieux de renvoyer un en-tête Cache-Control: no-cache de votre serveur quand même. Il offre une séparation plus nette des préoccupations.

Bien entendu, cela ne fonctionnerait pas pour les URL de service qui n'appartiennent pas à votre projet. Dans ce cas, vous pouvez envisager de remplacer le service tiers par un code serveur à partir du code du serveur plutôt que de l'appeler à partir du code client.

1
rstackhouse

Si vous utilisez IE 9, vous devez utiliser les éléments suivants devant la définition de la classe de votre contrôleur:

[OutputCache (NoStore = true, Duration = 0, VaryByParam = "*")]

classe publique TestController: Controller

Cela empêchera le navigateur de se mettre en cache.

Détails sur ce lien: http://dougwilsonsa.wordpress.com/2011/04/29/disabling-a9-ajax-response-caching-asp-net-mvc-3-jquery/

En fait, cela a résolu mon problème.

1
Net Solver

Si vous utilisez .net ASP MVC, désactivez la mise en cache de l'action du contrôleur en ajoutant l'attribut suivant à la fonction de point de terminaison: [OutputCacheAttribute (VaryByParam = "*", Duration = 0, NoStore = true) ]

1
Marius