Problema de almacenamiento en caché de IE angular por $ http


251

Angular almacena en caché todas las llamadas ajax que se envían desde el IE y obtengo un 304 responsepara todas las llamadas posteriores. Aunque la solicitud es la misma, la respuesta no será la misma en mi caso. Quiero deshabilitar este caché. Intenté agregar el cache attribute$ http.get pero aún así no ayudó. ¿Cómo se puede resolver este problema?

Respuestas:


439

En lugar de deshabilitar el almacenamiento en caché para cada solicitud GET, lo deshabilito 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';
}]);

78
El If-Modified-Sinceencabezado hace que IIS + iisnode arroje 400 solicitudes incorrectas por cada archivo html cargado a través de ngIncludey ngView. Sin embargo, los siguientes dos encabezados solucionaron el problema (los saqué de Chrome, que no tenía el problema de almacenamiento en caché): $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache'; $httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
Langdon

44
En mi opinión, esta respuesta debe marcarse como la respuesta, aunque la solución proporcionada por Martin funciona, es más un truco que una solución real.
Robba

44
Esto funcionó para mis solicitudes GET locales, pero provocó que la única solicitud CORS que estaba haciendo comenzara a usar el método OPTIONS en lugar del método GET. El servidor de terceros no admite el método OPTIONS, por lo que mi solución es usar jQuery.get () para hacer esa solicitud y usar $ scope.apply () en los controladores de respuestas.
Ben

13
El uso del If-Modified-Since = "0"encabezado rompe Tomcat (problema con el análisis de la fecha del encabezado, ya 0que no es un valor válido RFC ). Solucionado el uso de valor en su Mon, 26 Jul 1997 05:00:00 GMTlugar.
lopisan

66
No utilicé el encabezado "If-Modified-Since" y funcionó sin eso. Solo los otros dos son necesarios.
Michael Mahony

69

Puede agregar una cadena de consulta única (creo que esto es lo que hace jQuery con el caché: opción falsa) a la solicitud.

$http({
    url: '...',
    params: { 'foobar': new Date().getTime() }
})

Una solución quizás mejor es si tiene acceso al servidor, entonces puede asegurarse de que los encabezados necesarios estén configurados para evitar el almacenamiento en caché. Si está utilizando ASP.NET MVC esta respuesta, podría ayudar.


2
$http.get(url+ "?"+new Date().toString())es solo otra representación, sin usar el parámetro pero agregándolo a la cadena de consulta.
Davut Gürbüz

28

Puede agregar un interceptor.

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

debe eliminar las líneas de console.log después de verificar.


Y debe usarlo $logen caso de que se olvide de sacarlos.
Carl G

2
Tengo serios problemas de almacenamiento en caché en IE, lo que lleva a una página en blanco, porque partes importantes no se ejecutaron. ¡Usar el interceptor propinado resolvió este problema! +1
raoulinski

Creo que este es el mejor enfoque, ya que evita problemas con el comportamiento de CORS e IE de activar una solicitud de verificación previa si agrega encabezados adicionales. Este parece ser el método más seguro para no tener problemas adicionales
chrismarx

@dilip pattnaik: - ¿Por qué ocurre este problema con angular y ie?
MiHawk

14

Simplemente agregué tres metaetiquetas en index.html en el proyecto angular, y el problema de caché se resolvió en IE.

<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="Expires" content="Sat, 01 Dec 2001 00:00:00 GMT">

2
Ya teníamos esas metaetiquetas index.htmlcuando notamos que IE11 estaba almacenando en caché las solicitudes de AJAX: / ​​Pero la configuración $httpProvidercomo se muestra en otras respuestas funcionó bien.
walen

14

Duplicando mi respuesta en otro hilo .

Para Angular 2 y posteriores , la forma más fácil de agregar no-cacheencabezados anulando RequestOptions:

import { Injectable } from '@angular/core';
import { BaseRequestOptions, Headers } from '@angular/http';

@Injectable()
export class CustomRequestOptions extends BaseRequestOptions {
    headers = new Headers({
        'Cache-Control': 'no-cache',
        'Pragma': 'no-cache',
        'Expires': 'Sat, 01 Jan 2000 00:00:00 GMT'
    });
}

Y referencialo en tu módulo:

@NgModule({
    ...
    providers: [
        ...
        { provide: RequestOptions, useClass: CustomRequestOptions }
    ]
})

¿No serían esos encabezados para la respuesta del servidor, no para la solicitud del navegador? (Me imagino que se podría establecer If-Modified-Sinceuna fecha en el pasado usando el método anterior.)
Arjan

@Vitaliy: - ¿Por qué este problema ocurre con angular y ie?
MiHawk

Su enfoque eliminará cualquier encabezado personalizado que ya esté allí. Por lo tanto, haga lo siguiente en lugar de crear un nuevo objeto Encabezado. headers: req.headers .set('Cache-Control', 'no-cache') .set('Pragma', 'no-cache') .set('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT')
Chamika Goonetilaka

9

El garantizado que tenía trabajando era algo así:

myModule.config(['$httpProvider', function($httpProvider) {
    if (!$httpProvider.defaults.headers.common) {
        $httpProvider.defaults.headers.common = {};
    }
    $httpProvider.defaults.headers.common["Cache-Control"] = "no-cache";
    $httpProvider.defaults.headers.common.Pragma = "no-cache";
    $httpProvider.defaults.headers.common["If-Modified-Since"] = "Mon, 26 Jul 1997 05:00:00 GMT";
}]);

Tuve que fusionar 2 de las soluciones anteriores para garantizar el uso correcto de todos los métodos, pero puede reemplazarlo commoncon getotro método put, es decir post, deletepara que esto funcione en diferentes casos.


¿me puede decir en qué parte del código ha agregado esto al archivo angular.js? que linea #?
JonathanScialpi

@ JonathanScialpi Lo actualicé para mostrar dónde podría ponerlo. Dónde está dentro de la función anónima no debería importar.
marksyzm

@marksyzm ¿puedes decirme cuál es el significado de esta línea?if (!$httpProvider.defaults.headers.get) { $httpProvider.defaults.headers.common = {}; }
Monojit Sarkar

@MonojitSarkar Ah, se suponía que eran headers.common en la declaración if, gracias por ese puntero
marksyzm

1
["If-Modified-Since"] = "0"es ilegal y genera una solicitud incorrecta en algunos servidores. Debería ser una cita.
jenson-button-event

8

Esta única línea me ayudó (Angular 1.4.8):

$httpProvider.defaults.headers.common['Pragma'] = 'no-cache';

UPD: El problema es que IE11 hace un almacenamiento en caché agresivo. Cuando estaba buscando en Fiddler, noté que en el modo F12 las solicitudes envían "Pragma = no-cache" y se solicita un punto final cada vez que visito una página. Pero en modo normal, el punto final se solicitó solo una vez la primera vez que visité la página.


1
Solo para su información, esta respuesta causó un problema de CORS al solicitar archivos del almacenamiento de blobs de Azure, difícil de rastrear, pero finalmente descubrió que esta era la causa. La eliminación del encabezado pragma solucionó mi problema de CORS (pero reinstalé el problema de almacenamiento en caché de IE).
keithl8041

7

Para evitar el almacenamiento en caché, una opción es proporcionar una URL diferente para el mismo recurso o datos. Para generar una URL diferente, puede agregar una cadena de consulta aleatoria al final de la URL. Esta técnica funciona para JQuery, Angular u otro tipo de solicitudes ajax.

myURL = myURL +"?random="+new Date().getTime();

6

Lo resuelvo agregando datetime como un número aleatorio:

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

: - ¿Por qué ocurre este problema con angular y es decir?
MiHawk

4

La solución anterior funcionará (haga que la url sea única agregando en la cadena de consulta un nuevo parámetro), pero prefiero que la solución proponga [aquí]: ¿ Mejor manera de prevenir el caché de IE en AngularJS? , que manejan esto a nivel de servidor, ya que no es específico de IE. Quiero decir, si ese recurso no debe almacenarse en caché, hágalo en el servidor (esto no tiene nada que ver con el navegador utilizado; es intrínseco al recurso).

Por ejemplo, en java con JAX-RS, hágalo programáticamente para JAX-RS v1 o declarativamente para JAX-RS v2.

Estoy seguro de que alguien descubrirá cómo hacerlo


1
Aunque se puede elaborar, esta es la forma correcta de hacerlo. El lado del cliente no debe elegir qué almacenar en caché o no, pero debe ser el servidor quien debe decirle al cliente qué debe almacenarse en caché o no.
Arquímedes Trajano

Estoy totalmente de acuerdo, esto debe ser una forma adecuada
smnbbrv

1

Esto es un poco viejo pero: las soluciones como son obsoletas. Deje que el servidor maneje el caché o no el caché (en la respuesta). La única forma de garantizar que no haya almacenamiento en caché (pensando en nuevas versiones en producción) es cambiar el archivo js o css con un número de versión. Hago esto con webpack.


1

También puede intentar en su servicio configurar encabezados como, por ejemplo:

...
importar {Inyectable} desde "@ angular / core";
importar {HttpClient, HttpHeaders, HttpParams} desde "@ angular / common / http";
...
 @Inyectable ()
clase de exportación MyService {

    encabezados privados: HttpHeaders;


    constructor (http privado: HttpClient ..) 
    {


        this.headers = new HttpHeaders ()
                    .append ("Content-Type", "application / json")
                    .append ("Aceptar", "aplicación / json")
                    .append ("LanguageCulture", this.headersLanguage)
                    .append ("Cache-Control", "no-cache")
                    .append ("Pragma", "sin caché")                   
    }
}
....


0

Este problema se debe al problema de almacenamiento en caché de IE, como dijiste, puedes probarlo en modo de depuración de IE presionando f12 (esto funcionará bien en modo de depuración) .IE no tomará los datos del servidor cada vez que llame la página. Los datos del caché. Para deshabilitar esto, realice una de las siguientes acciones:

  1. agregue lo siguiente con su URL de solicitud de servicio http

// Antes (emitió uno)

this.httpService.get (this.serviceUrl + "/eAMobileService.svc/ValidateEngagmentName/" + engagementName, {})

// Después (trabajando bien)

this.httpService.get (this.serviceUrl + "/eAMobileService.svc/ValidateEngagmentName/" + engagementName + "? DateTime =" + new Date (). getTime () + '', {cache: false})

  1. deshabilitar el caché para todo el Módulo: -

$ httpProvider.defaults.headers.common ['Pragma'] = 'no-cache';


0
meta http-equiv="Cache-Control" content="no-cache"

Acabo de agregar esto a View y comenzó a funcionar en IE. Confirmado para trabajar en Angular 2.


0

Una opción es utilizar el enfoque simple de agregar una marca de tiempo con cada solicitud sin necesidad de borrar el caché.

    let c=new Date().getTime();
    $http.get('url?d='+c)

-2

Prueba esto, funcionó para mí en un caso similar:

$http.get("your api url", {
headers: {
    'If-Modified-Since': '0',
    "Pragma": "no-cache",
    "Expires": -1,
    "Cache-Control": "no-cache, no-store, must-revalidate"
 }
})
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.