Problema no cache do IE angular por US $ http


251

Todas as chamadas ajax enviadas do IE são armazenadas em cache pelo Angular e recebo um 304 responsepara todas as chamadas subseqüentes. Embora a solicitação seja a mesma, a resposta não será a mesma no meu caso. Eu quero desativar esse cache. Eu tentei adicionar o cache attribute$ http.get, mas ainda assim não ajudou. Como esse problema pode ser resolvido?

Respostas:


439

Em vez de desabilitar o cache para cada solicitação GET, desabilito-o globalmente no $ 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
O If-Modified-Sincecabeçalho faz com que o IIS + iisnode lance 400 solicitações incorretas para cada arquivo html carregado com ngIncludee ngView. Os dois cabeçalhos a seguir corrigiram o problema para mim (eu os tirei do Chrome, que não apresentava o problema de armazenamento em cache): $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache'; $httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
Langdon

4
Na minha opinião, essa resposta deve ser marcada como a resposta, embora a solução fornecida por Martin funcione, é mais um hack do que uma correção real.
Robba 23/05

4
Isso funcionou para minhas solicitações locais GET, mas fez com que a única solicitação CORS que eu estava fazendo iniciasse o uso do método OPTIONS em vez do método GET. O servidor de terceiros não suporta o método OPTIONS, portanto, minha solução alternativa é usar o jQuery.get () para fazer essa solicitação e usar $ scope.apply () nos manipuladores de resposta.
Ben

13
O uso do If-Modified-Since = "0"cabeçalho interrompe o Tomcat (problema com a análise da data do cabeçalho, pois o 0valor RFC não é válido ). Corrigido usando valor Mon, 26 Jul 1997 05:00:00 GMT.
lopisan

6
Eu não usei o cabeçalho "If-Modified-Since" e funcionou sem isso. Apenas os outros dois são necessários.
Michael Mahony

69

Você pode acrescentar uma string de consulta exclusiva (acredito que é isso que o jQuery faz com a opção cache: false) à solicitação.

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

Talvez uma solução melhor seja, se você tiver acesso ao servidor, verifique se os cabeçalhos necessários estão definidos para impedir o armazenamento em cache. Se você estiver usando ASP.NET MVC esta resposta, pode ajudar.


2
$http.get(url+ "?"+new Date().toString())é apenas outra representação, sem usar o parâmetro, mas adicionando-o à string de consulta.
Davut Gürbüz

28

você pode adicionar um interceptador.

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

você deve remover as linhas console.log após a verificação.


E você deve usá- $loglo caso se esqueça de retirá-los.
Carl G

2
Estou tendo sérios problemas de armazenamento em cache no IE, o que leva a uma página em branco, porque partes importantes não foram executadas. O uso do interceptor proposto resolveu esse problema! +1
raoulinski 25/03

Acho que essa é a melhor abordagem, pois evita problemas com o comportamento do CORS e do IE de acionar uma solicitação de comprovação, se você adicionar cabeçalhos adicionais. Este parece ser o método mais seguro para não ter problemas adicionais
chrismarx

@dilip pattnaik: - Por que esse problema ocorre com angular e ie?
Mihawk

14

Simplesmente adicionei três metatags no index.html no projeto angular e o problema de cache foi resolvido no 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
Já tínhamos essas metatags em nosso index.htmlarquivo quando notamos que o IE11 estava armazenando em cache solicitações AJAX: / ​​Mas a configuração $httpProviderconforme mostrado em outras respostas funcionou bem.
walen

14

Duplicando minha resposta em outro tópico .

Para Angular 2 e versões mais recentes , a maneira mais fácil de adicionar no-cachecabeçalhos substituindo 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'
    });
}

E referencie-o no seu módulo:

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

Esses não seriam cabeçalhos para a resposta do servidor, não para a solicitação do navegador? (I pode imaginar um poderia definir If-Modified-Sincecom alguns data longe no passado usando o método acima descrito.)
Arjan

@ Vitaliy: - Por que esse problema ocorre com angular e ou seja?
Mihawk

Sua abordagem removerá os cabeçalhos personalizados que já estão lá. Portanto, faça o seguinte em vez de criar um novo objeto Header. 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

O garantido que eu tinha trabalhado era algo nesse sentido:

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

Eu tive que mesclar 2 das soluções acima, a fim de garantir o uso correto para todos os métodos, mas você pode substituir commonpor getou outro método put, ou seja post, deletepara fazer isso funcionar em casos diferentes.


você pode me dizer onde, no código, você adicionou isso ao arquivo angular.js? qual linha #?
JonathanScialpi

@JonathanScialpi Atualizei-o para mostrar onde devo colocá-lo. Onde está dentro da função anônima não deve importar.
marksyzm

@marksyzm pode u plzz me dizer qual é o significado desta linhaif (!$httpProvider.defaults.headers.get) { $httpProvider.defaults.headers.common = {}; }
Monojit Sarkar

@MonojitSarkar Ah, que era suposto ser headers.common no if, obrigado por esse ponteiro
marksyzm

1
["If-Modified-Since"] = "0"é ilegal e gera uma solicitação incorreta em alguns back-ends. deve ser uma data.
Jenson-button-event

8

Essa única linha me ajudou (Angular 1.4.8):

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

UPD: O problema é que o IE11 faz cache agressivo. Quando eu estava olhando para o Fiddler, notei que, no modo F12, as solicitações estão enviando "Pragma = no-cache" e o endpoint é solicitado toda vez que visito uma página. Mas, no modo normal, o terminal foi solicitado apenas uma vez na primeira vez em que visitei a página.


1
Apenas para sua informação, esta resposta causou um problema de CORS ao solicitar arquivos do armazenamento de blobs do Azure, difícil de rastrear, mas acabou descobrindo que essa era a causa. A remoção do cabeçalho pragma corrigiu meu problema do CORS (mas restabeleceu o problema do cache do IE).
precisa saber é o seguinte

7

Para evitar o armazenamento em cache, uma opção é fornecer URL diferente para o mesmo recurso ou dados. Para gerar um URL diferente, você pode adicionar uma sequência de consulta aleatória ao final do URL. Essa técnica funciona para solicitações JQuery, Angular ou outro tipo de ajax.

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

6

Eu resolvo acrescentando datetime como um número aleatório:

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

: - Por que esse problema ocorre com angular e ie?
Mihawk

4

A solução acima funcionará (torne o URL exclusivo adicionando na querystring um novo parâmetro), mas eu prefiro a proposta de solução [aqui]: Melhor maneira de impedir o cache do IE no AngularJS? , que lidam com isso no nível do servidor, pois não é específico para o IE. Quero dizer, se esse recurso não deve ser armazenado em cache, faça-o no servidor (isso não tem nada a ver com o navegador usado; é intrínseco ao recurso).

Por exemplo, em java com JAX-RS, faça-o programaticamente para JAX-RS v1 ou declativamente para JAX-RS v2.

Tenho certeza que alguém vai descobrir como fazê-lo


1
Embora possa ser elaborado, esta é a maneira correta de fazê-lo. O lado do cliente não deve escolher o que armazenar em cache ou não, mas deve ser o servidor que deve informar ao cliente o que precisa ser armazenado em cache ou não.
Archimedes Trajano

Concordo plenamente, este deve ser um bom caminho
smnbbrv

1

Isso é um pouco antigo, mas: Soluções como estão obsoletas. Deixe o servidor manipular o cache ou não o cache (na resposta). A única maneira de garantir nenhum armazenamento em cache (pensando em novas versões em produção) é alterar o arquivo js ou css com um número de versão. Eu faço isso com o webpack.


1

Além disso, você pode tentar em seu serviço definir cabeçalhos como por exemplo:

...
import {Injetável} de "@ angular / core";
import {HttpClient, HttpHeaders, HttpParams} de "@ angular / common / http";
...
 @Injectable ()
classe de exportação MyService {

    cabeçalhos privados: HttpHeaders;


    construtor (http privado: HttpClient ..) 
    {


        this.headers = new HttpHeaders ()
                    .append ("Tipo de conteúdo", "application / json")
                    .append ("Aceitar", "application / json")
                    .append ("LanguageCulture", this.headersLanguage)
                    .append ("Controle de cache", "sem cache")
                    .append ("Pragma", "sem cache")                   
    }
}
....


0

Este problema ocorre devido ao problema de armazenamento em cache do IE, como você disse, você pode testá-lo no modo de depuração do IE pressionando f12 (isso funcionará bem no modo de depuração). os dados do cache. Para desabilitar isso, siga um destes procedimentos:

  1. anexe o seguinte ao seu URL de solicitação de serviço http

// Antes (emitido um)

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

// Depois (funcionando bem)

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

  1. desative o cache para todo o módulo: -

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


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

Acabei de adicionar isso ao View e ele começou a trabalhar no IE. Confirmado para trabalhar no Angular 2.


0

Uma opção é usar a abordagem simples de adicionar um carimbo de data / hora a cada solicitação, sem a necessidade de limpar o cache.

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

-2

Tente isso, funcionou para mim em um caso semelhante: -

$http.get("your api url", {
headers: {
    'If-Modified-Since': '0',
    "Pragma": "no-cache",
    "Expires": -1,
    "Cache-Control": "no-cache, no-store, must-revalidate"
 }
})
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.