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?

Rahul
fonte

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

Martin
fonte
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.

dillip pattnaik
fonte
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">
rtato
fonte
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 }
    ]
})
Vitaliy Ulantikov
fonte
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.

marksyzm
fonte
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.

yamaxim
fonte
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();
Razan Paul
fonte
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!!!');
});
khichar.anil
fonte
: - 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

rguitter
fonte
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.

Jens Alenius
fonte
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")                   
    }
}
....
Sem nome
fonte
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';

Nijas_kp
fonte
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.

Cerveja de gengibre
fonte
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)
Vaimeo
fonte
-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"
 }
})
Mayank Parnami
fonte