¿Mejor forma de prevenir la caché de IE en AngularJS?

Actualmente uso service / $ resource para hacer llamadas ajax (GET en este caso) e IE almacena en caché las llamadas para que no se puedan recuperar los datos nuevos del servidor. He utilizado una técnica que encontré al buscar en Google para crear un número aleatorio y anexarlo a la solicitud, para que IE no vaya a la memoria caché de los datos.

¿Hay una mejor manera que agregar el cacheKill a cada solicitud?

código de fábrica

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

Llamada desde el controlador

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

Como binarygiant solicitó, estoy publicando mi comentario como respuesta. He resuelto este problema agregando encabezados No-Cache a la respuesta en el lado del servidor. Tenga en cuenta que debe hacer esto solo para solicitudes GET, otras solicitudes parecen funcionar bien.

binarygiant publicó cómo puedes hacer esto en node / express. Puedes hacerlo en ASP.NET MVC de esta manera:

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

Como se describe en una de mis otras publicaciones , puede deshabilitar el almacenamiento en caché globalmente en $ 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'; }]); 

Para aquellos que usan ASP.NET Web API 2, la solución equivalente sería esta (Web API no usa la misma lógica de almacenamiento en caché 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; } } } } 

luego adjúntelo en 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 } ); } 

Habilitar noCache en la instancia de is era la mejor manera de lograr esto:

En node / express esto funciona para evitar que IE almacene en caché esas solicitudes:

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

puede agregar un interceptor para generar URL de solicitud única. Además, puede eliminar las llamadas a 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; } }; }); 

Lo resuelvo por:

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

Si bien este enfoque:

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

Es correcto, ‘0’ no es un valor válido para el encabezado If-Modified-Since. Debe ser una fecha HTTP válida, por ejemplo:

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

De acuerdo con la especificación :

Un destinatario DEBE ignorar el campo de encabezado If-Modified-Since si el
el valor de campo recibido no es una fecha HTTP válida, o si la solicitud
método no es GET ni HEAD.

Así que es mejor estar a salvo que lamentar y usar una fecha real en el pasado.

Si tiene algún control sobre la salida del servidor, sería preferible no agregar encabezados de caché a eso.

Koajs equivalente a la respuesta 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; } 

Mi solución fue agregar Cache-Control: no-cache encabezado Cache-Control: no-cache en el servidor, además de agregar $templateCache.remove() antes de cambiar el estado. Estoy usando angular-ui / ui-router. Estaba teniendo problemas con IE11 y el navegador Edge.

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

Una solución obvia es usar urls únicas. Pero, ¿cómo pueden cambiarse las URL del enrutador después de la inicialización? Deshabilitar las cachés del navegador no es una opción, ya que lo necesitamos para las operaciones normales. Puede eliminar plantillas de $ templateCache cuando ya no sean necesarias. ( http://docs.angularjs.org/api/ng . $ templateCache). Esos nuevos se agregan a la memoria caché tan pronto como se completa la descarga.