关于javascript:$ http的Angular IE Caching问题

Angular IE Caching issue for $http

从IE发送的所有Ajax调用都是由Angular缓存的,对于所有后续调用,我都会得到一个304 response。尽管请求是相同的,但在我的情况下,响应是不一样的。我想禁用这个缓存。我试着把cache attribute添加到$http.get中,但还是没有用。如何解决这个问题?


我没有为每个GET请求禁用缓存,而是在$httpprovider中全局禁用它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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';
}]);


您可以向请求附加一个唯一的querystring(我相信这就是jquery对cache:false选项所做的操作)。

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

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


您可以添加一个拦截器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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行。


我在AngularProject的index.html中简单地添加了三个元标记,缓存问题在IE中得到了解决。

1
2
3
<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">


在另一条线上复制我的答案。

对于Angular 2和更新版本,最简单的方法是通过覆盖RequestOptions来添加no-cache头部:

1
2
3
4
5
6
7
8
9
10
11
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'
    });
}

并在模块中引用:

1
2
3
4
5
6
7
@NgModule({
    ...
    providers: [
        ...
        { provide: RequestOptions, useClass: CustomRequestOptions }
    ]
})


我工作过的有保证的是这样的:

1
2
3
4
5
6
7
8
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";
}]);

为了保证所有方法的正确使用,我不得不合并上述两种解决方案,但您可以用get或其他方法(如putpostdelete)代替common


这条唯一的线帮助了我(角度1.4.8):

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

upd:问题是IE11执行攻击性缓存。当我查看fiddler时,我注意到在F12模式下,请求发送的是"pragma=no cache",每次访问页面时都请求端点。但是在正常模式下,当我第一次访问页面时,只请求一次端点。


为了避免缓存,一个选项是为同一资源或数据提供不同的URL。要生成不同的URL,可以在URL末尾添加一个随机查询字符串。此技术适用于jquery、angular或其他类型的Ajax请求。

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

我得到的结果是将datetime作为一个随机数追加:

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


上面的解决方案可以工作(通过在querystring中添加一个新参数使url唯一),但是我更喜欢解决方案建议[这里]:更好的方法来防止在angularjs中使用ie缓存?,它在服务器级别处理这个问题,因为它不是特定于IE的。我的意思是,如果不应该缓存该资源,则在服务器上执行(这与所使用的浏览器无关;它与资源无关)。

例如,在JAX-JAVA中,用JAX-RS V1或JAX-RS V2进行编程。

我相信有人会想办法的


这有点老生常谈,但是:像这样的解决方案已经过时了。让服务器处理缓存或不处理缓存(在响应中)。保证没有缓存(考虑到生产中的新版本)的唯一方法是使用版本号更改JS或CSS文件。我用Webpack做这个。


还可以尝试在服务中设置头,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
import { Injectable } from"@angular/core";
import { HttpClient, HttpHeaders, HttpParams } from"@angular/common/http";
...
 @Injectable()
export class MyService {

    private headers: HttpHeaders;


    constructor(private http: HttpClient..)
    {


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

我找到了更好的解决方案:更好的方法来防止在AngularJS中使用IE缓存?

对于懒惰的人,这里有一个解决方案:

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

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

  • 将以下内容附加到HTTP服务请求URL中
  • //之前(发布一个)

    this.httpservice.get(this.serviceurl+"/eamobileservice.svc/validateengagementname/"+engagementname,)

    //之后(工作正常)

    this.httpservice.get(this.serviceurl+"/eamobileservice.svc/validateengagementname/"+engagementname+"?datetime="+new date().gettime()+",缓存:false)

  • 禁用整个模块的缓存:
  • $httpprovider.defaults.headers.common['pragma']='no cache';


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

    我刚把这个添加到视图中,它开始在IE上工作,确认在Angular2上工作。


    始终使用简单的方法添加时间戳,每个请求不需要清除缓存

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


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

    1
    2
    3
    4
    5
    6
    7
    8
    $http.get("your api url", {
    headers: {
        'If-Modified-Since': '0',
       "Pragma":"no-cache",
       "Expires": -1,
       "Cache-Control":"no-cache, no-store, must-revalidate"
     }
    })