Лучший способ предотвратить кэш IE в AngularJS?


в настоящее время я использую service/$resource для выполнения вызовов ajax (GET в этом случае), а IE кэширует вызовы, чтобы свежие данные не могли быть получены с сервера. Я использовал метод, который я нашел в Google, чтобы создать случайное число и добавить его к запросу, так что IE не будет идти в кэш для данных.

есть ли лучший способ, чем добавление cacheKill к каждому запросу?

код

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

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

вызов от контроллера

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

10 ответов:

Как binarygiant просил я публикую свой комментарий в качестве ответа. Я решил эту проблему, добавив заголовки без кэша в ответ на стороне сервера. Обратите внимание, что вы должны сделать это только для запросов GET, другие запросы, похоже, работают нормально.

binarygiant опубликовал, как вы можете сделать это на node/express. Вы можете сделать это в ASP.NET MVC вот так:

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

как описано в одном из моих других посты, вы можете отключить кэширование глобально в $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';
}]);

для тех, кто использует ASP.NET Web API 2 эквивалентное решение будет следующим (Web API не использует ту же логику кэширования, что и 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;
            }
         }
    }
}

затем прикрепите его в 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 }
    );
}

включение noCache в экземпляре is было лучшим способом выполнить это:

в node / express это работает, чтобы предотвратить IE от кэширования этих запросов:

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();
});

вы можете добавить перехватчик для создания уникального url запроса. Также вы можете удалить консоль.журнал вызовов

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;
               }
           };
    });

Я получаю это решение:

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

при таком подходе:

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';
}]);

правильно, '0' не является допустимым значением для заголовка If-Modified-Since. Это должна быть допустимая HTTP-дата, например:

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

по словам spec:

получатель должен игнорировать поле заголовка If-Modified-Since, если
полученное значение поля не является допустимой HTTP-датой, или если запрос
метод-это ни получить, ни голова.

Так что лучше быть безопасный, чем жаль, и использовать фактическую дату в прошлом.

Если у вас есть какой-либо контроль над выводом сервера, было бы предпочтительно не добавлять к нему заголовки кэширования.

эквивалент Коайса ответа 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;
}

мое решение было добавить Cache-Control: no-cache заголовок на сервере, плюс добавление $templateCache.remove() перед изменением состояния. Я использую angular-ui / ui-router. У меня была проблема с IE11 и Edge browser.

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

очевидным решением является использование уникальных URL-адресов. Но как можно изменить URL-адреса маршрутизатора после инициализации Отключение кэша браузера не является опцией, так как нам это нужно для нормальной работы. Вы можете удалить шаблоны из $ templateCache, когда их нет нужно больше времени. (http://docs.angularjs.org/api/ng.$templateCache). Эти новые добавляются в кэш, как только загрузка завершается.