Лучший способ предотвратить кэш 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 ответов:
Как 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). Эти новые добавляются в кэш, как только загрузка завершается.