$ http的Angular IE缓存问题


251

从IE发送的所有ajax调用都被Angular缓存,我304 response为所有后续调用获取了a 。尽管请求是相同的,但在我的情况下响应不会是相同的。我想禁用此缓存。我尝试将其添加cache attribute到$ http.get中,但仍然没有帮助。该问题如何解决?

Answers:


439

我没有为每个GET请求禁用缓存,而是在$ 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
If-Modified-Since头品牌IIS + iisnode掷通过加载的每一个HTML文件400错误的请求ngIncludengView。不过,以下两个标头为我解决了这个问题(我从没有缓存问题的Chrome浏览器中拉出了它们): $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache'; $httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
Langdon 2014年

4
在我看来,这个答案应该标记为答案,尽管Martin提供的解决方案确实有效,但它更多的是破解而不是实际的修复。
罗巴2014年

4
这对我的本地GET请求有效,但是却导致我开始使用OPTIONS方法而不是GET方法发出的一个CORS请求。第三方服务器不支持OPTIONS方法,因此我的解决方法是使用jQuery.get()发出该请求,并在响应处理程序中使用$ scope.apply()。

13
If-Modified-Since = "0"标头的用法破坏了Tomcat(解析标头日期的问题,因为0无效值RFC)。固定使用值Mon, 26 Jul 1997 05:00:00 GMT代替。
lopisan 2014年

6
我没有使用“ If-Modified-Since”标头,没有它就可以了。仅另外两个是必要的。
Michael Mahony 2015年

69

您可以在请求中附加一个唯一的查询字符串(我相信这就是jQuery对cache的作用:false选项)。

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

也许更好的解决方案是,如果您有权访问服务器,则可以确保设置了必要的标头以防止缓存。如果您使用的是ASP.NET MVC 此答案,则可能会有所帮助。


2
$http.get(url+ "?"+new Date().toString())只是另一种表示形式,不使用参数而是将其添加到查询字符串中。
DavutGürbüz16年

28

您可以添加一个拦截器。

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

您应该在验证后删除console.log行。


$log如果您忘记将它们取出,则应该使用。
卡尔·G

2
我在IE中遇到严重的缓存问题,导致空白页面,因为重要部分没有执行。使用道具拦截器解决了这个问题!+1
raoulinski 2015年

我认为这是最好的方法,因为它避免了CORS和IE添加新标头时触发预检请求的行为问题。这似乎是不遇到其他问题的最安全方法
chrismarx

@dilip pattnaik:-为什么这个问题发生在angular和ie上?
MiHawk '18

14

我只是将三个meta标签添加到angular项目的index.html中,并且在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
index.html当我们注意到IE11正在缓存AJAX请求时,我们已经有了这些元标记:/但是$httpProvider按照其他答案所示进行配置可以正常工作。
walen

14

我的答案复制到另一个线程中

对于Angular 2和更高版本no-cache通过重写添加标题的最简单方法是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'
    });
}

并在您的模块中引用它:

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

这些不是服务器响应的标头,不是浏览器请求的标头吗?(我可以想象If-Modified-Since使用上述方法可以设置过去的某个日期。)
Arjan

@Vitaliy:-为什么此问题发生在angular和ie上?
MiHawk

您的方法将删除任何已经存在的自定义标头。因此,请执行以下操作,而不是创建新的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

我所保证的工作是遵循以下原则:

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

为了保证所有方法的正确使用,我不得不合并上述两种解决方案,但是您可以common使用get或替换其他方法put,例如postdelete以使这种方法适用于不同的情况。


您能告诉我在代码中将其添加到angular.js文件中的什么位置吗?第几行?
JonathanScialpi

@JonathanScialpi我对其进行了更新,以显示可以放在哪里。它在匿名函数中的位置无关紧要。
markyzm

@marksyzm您能告诉我这条线是什么意思if (!$httpProvider.defaults.headers.get) { $httpProvider.defaults.headers.common = {}; }
Monojit Sarkar

@MonojitSarkar啊,应该在if语句中为headers.common,感谢该指针
marksyzm

1
["If-Modified-Since"] = "0"是非法的,并在某些后端生成错误请求。它应该是一个日期。
jenson-button-event

8

这条线对我有所帮助(角度1.4.8):

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

UPD:问题是IE11进行了主动缓存。当我查看Fiddler时,我注意到在F12模式下,请求正在发送“ Pragma = no-cache”,并且每次访问页面时都请求终结点。但是在正常模式下,当我第一次访问该页面时,端点仅被请求一次。


1
仅供参考,从Azure的Blob存储请求文件时,此答案导致了CORS问题,难以跟踪,但最终找出了原因。删除杂项标头修复了我的CORS问题(但重新设置了IE缓存问题)。
keithl8041 2015年

7

为了避免缓存,一种选择是为相同的资源或数据提供不同的URL。要生成其他URL,可以在URL末尾添加随机查询字符串。该技术适用于JQuery,Angular或其他类型的ajax请求。

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

6

我解决了将datetime追加为随机数的问题:

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

:-为什么用angular和ie会发生此问题?
MiHawk

4

上面的解决方案可以工作(通过在querystring中添加新参数使URL唯一),但我更喜欢提出的解决方案[here]:防止AngularJS中的IE缓存的更好方法?,它在服务器级别处理此问题,因为它不是特定于IE的。我的意思是,如果不应该缓存该资源,请在服务器上进行此操作(这与所使用的浏览器无关;这对资源而言是固有的)。

例如,在具有JAX-RS的Java中,以编程方式针对JAX-RS v1或以 隐蔽方式针对JAX-RS v2进行此操作。

我敢肯定有人会想办法


1
尽管可以详细说明,但这是正确的方法。客户端不应选择是否要缓存什么,而应该由服务器来告诉客户端需要缓存或不缓存什么。
阿基米德·特拉哈诺2015年

我完全同意,这必须是正确的方法
smnbbrv 2015年

1

这有点陈旧,但:解决方案已过时。让服务器处理缓存还是不缓存(在响应中)。保证不进行缓存(考虑生产中的新版本)的唯一方法是使用版本号更改js或css文件。我用webpack做到这一点。


1

您也可以尝试使用servce设置标头,例如:

...
从“ @ angular / core”导入{可注射};
从“ @ angular / common / http”导入{HttpClient,HttpHeaders,HttpParams};
...
 @Injectable()
导出类MyService {

    专用标头:HttpHeaders;


    构造函数(私有http:HttpClient ..) 
    {


        this.headers =新的HttpHeaders()
                    .append(“ Content-Type”,“ application / json”)
                    .append(“ Accept”,“ application / json”)
                    .append(“ LanguageCulture”,this.headersLanguage)
                    .append(“ Cache-Control”,“ no-cache”)
                    .append(“ Pragma”,“ no-cache”)                   
    }
}
....


0

这个问题是由于您所说的IE缓存问题造成的,您可以按f12在IE调试模式下对其进行测试(这在调试模式下可以正常工作).IE不会在每次页面调用时都获取服务器数据,缓存中的数据。要禁用此功能,请执行以下任一操作:

  1. 在您的http服务请求网址后面附加以下内容

//之前(发布一个)

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

//之后(工作正常)

this.httpService.get(this.serviceUrl +“ /eAMobileService.svc/ValidateEngagmentName/” +参与名称+“?DateTime =” + new Date()。getTime()+'',{缓存:false})

  1. 禁用整个模块的缓存:

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


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

我刚刚将其添加到View,它开始在IE上运行。确认可以在Angular 2上使用。


0

一种选择是使用为每个请求添加时间戳的简单方法,而无需清除缓存。

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

-2

试试这个,它在类似的情况下对我有用:

$http.get("your api url", {
headers: {
    'If-Modified-Since': '0',
    "Pragma": "no-cache",
    "Expires": -1,
    "Cache-Control": "no-cache, no-store, must-revalidate"
 }
})
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.