web-dev-qa-db-fra.com

Meilleure façon de prévenir IE Cache dans AngularJS?

J'utilise actuellement service/$ resource pour passer des appels ajax (GET dans ce cas) et IE met en cache les appels afin que les nouvelles données ne puissent pas être extraites du serveur. J'ai utilisé une technique que j'ai trouvée. en googlant pour créer un nombre aléatoire et l'ajouter à la demande, de sorte que IE ne sera pas mis en cache pour les données.

Existe-t-il un meilleur moyen que d’ajouter le cacheKill à chaque requête?

code d'usine

.factory('UserDeviceService', function ($resource) {

        return $resource('/users/:dest', {}, {
            query: {method: 'GET', params: {dest: "getDevicesByUserID"}, isArray: true }
        });

Appel du contrôleur

$scope.getUserDevices = function () {
        UserDeviceService.query({cacheKill: new Date().getTime()},function (data) {
            //logic
        });
    }
60
binarygiant

Comme l'a demandé binarygiant, je poste mon commentaire comme réponse. J'ai résolu ce problème en ajoutant des en-têtes No-Cache à la réponse côté serveur. Notez que vous devez le faire uniquement pour les demandes GET, les autres demandes semblent fonctionner correctement.

binarygiant a posté comment vous pouvez faire cela sur node/express. Vous pouvez le faire dans ASP.NET MVC comme ceci:

[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
public ActionResult Get()
{
    // return your response
}
36

Comme décrit dans l'un de mes autres publications , vous pouvez désactiver la mise en cache globalement dans $ httpProvider:

myModule.config(['$httpProvider', function($httpProvider) {
    //initialize get if not there
    if (!$httpProvider.defaults.headers.get) {
        $httpProvider.defaults.headers.get = {};    
    }    

    // Answer edited to include suggestions from comments
    // because previous version of code introduced browser-related errors

    //disable IE ajax request caching
    $httpProvider.defaults.headers.get['If-Modified-Since'] = 'Mon, 26 Jul 1997 05:00:00 GMT';
    // extra
    $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache';
    $httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
}]);
50
cnmuc

Pour ceux qui utilisent ASP.NET Web API 2, la solution équivalente serait la suivante (l’API Web n’utilise pas la même logique de mise en cache que MVC):

public class NoCacheHeaderFilter : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        if (actionExecutedContext.Response != null) // can be null when exception happens
        {
            actionExecutedContext.Response.Headers.CacheControl =
                new CacheControlHeaderValue { NoCache = true, NoStore = true, MustRevalidate = true };
            actionExecutedContext.Response.Headers.Pragma.Add(new NameValueHeaderValue("no-cache"));

            if (actionExecutedContext.Response.Content != null) // can be null (for example HTTP 400)
            {
                actionExecutedContext.Response.Content.Headers.Expires = DateTimeOffset.UtcNow;
            }
         }
    }
}

puis attachez-le dans WebApiConfig.cs:

public static void Register(HttpConfiguration config)
{
    ....
    config.Filters.Add(new NoCacheHeaderFilter());

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}
33
UserControl

Activer noCache dans l'instance is était le meilleur moyen d'y parvenir:

Dans node/express, cela empêche IE de mettre en cache ces requêtes:

app.use(function noCache(req, res, next) {
    res.header("Cache-Control", "no-cache, no-store, must-revalidate");
    res.header("Pragma", "no-cache");
    res.header("Expires", 0);
    next();
});
33
binarygiant

vous pouvez ajouter un intercepteur pour générer une URL de requête unique. Vous pouvez aussi supprimer les appels console.log

myModule.config(['$httpProvider', function($httpProvider) {
 $httpProvider.interceptors.Push('noCacheInterceptor');
}]).factory('noCacheInterceptor', function () {
            return {
                request: function (config) {
                    console.log(config.method);
                    console.log(config.url);
                    if(config.method=='GET'){
                        var separator = config.url.indexOf('?') === -1 ? '?' : '&';
                        config.url = config.url+separator+'noCache=' + new Date().getTime();
                    }
                    console.log(config.method);
                    console.log(config.url);
                    return config;
               }
           };
    });
12
dillip pattnaik

Je l'obtiens résolu par:

$http.get("/your_url?rnd="+new Date().getTime()).success(function(data, status, headers, config) {
    console.log('your get response is new!!!');
});
4
khichar.anil

L'équivalent Koaj de la réponse de binarygiant:

app.use(route.get('*', noCache));

function* noCache(path, next){
    this.set('cache-control', 'no-cache, no-store, must-revalidate');
    this.set('pragma',  'no-cache');
    this.set('expires', 0);
    yield next;
}
4
Felix

Alors que cette approche:

myModule.config(['$httpProvider', function($httpProvider) {
    //initialize get if not there
    if (!$httpProvider.defaults.headers.get) {
        $httpProvider.defaults.headers.get = {};    
    }
    //disable IE ajax request caching
    $httpProvider.defaults.headers.get['If-Modified-Since'] = '0';
}]);

Est correct, "0" n'est pas une valeur valide pour l'en-tête If-Modified-Since. Il doit s'agir d'une date HTTP valide, par exemple:

If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT

Selon le spec :

Un destinataire DOIT ignorer le champ d’en-tête If-Modified-Since si le
valeur de champ reçue n'est pas une date HTTP valide, ou si la demande
La méthode n'est ni GET ni HEAD.

Alors, mieux vaut prévenir que guérir et utiliser une date du passé.

Si vous avez un quelconque contrôle sur la sortie du serveur, il serait préférable de ne pas y ajouter d’en-têtes de mise en cache.

3
Brother Woodrow

Ma solution consistait à ajouter un en-tête Cache-Control: no-cache Sur le serveur, en plus d'ajouter $templateCache.remove() avant de changer d'état. J'utilise angular-ui/ui-router. J'avais un problème avec IE11 et le navigateur Edge.

$templateCache.remove('/partials/details.html');
$state.go('details');
2
Hexadecy