ChatGPT解决这个技术问题 Extra ChatGPT

Angular IE Caching issue for $http

All the ajax calls that are sent from the IE are cached by Angular and I get a 304 response for all the subsequent calls. Although the request is the same, the response is not going be the same in my case. I want to disable this cache. I tried adding the cache attribute to $http.get but still it didn't help. How can this issue be resolved?


n
nikib3ro

Instead of disabling caching for each single GET-request, I disable it globally in the $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';
}]);

The If-Modified-Since header makes IIS+iisnode throw 400 Bad Request for every html file loaded through ngInclude and ngView. The following two headers fixed the issue for me though (I pulled them from Chrome, which didn't have the caching issue): $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache'; $httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
In my opinion this answer should be marked as the answer, while the solution provided by Martin does work, it's more of a hack than an actual fix.
This worked for my local GET requests, but it caused the one CORS request I was making to start using the OPTIONS method instead of the GET method. The 3rd party server doesn't support the OPTIONS method, so my workaround is to use jQuery.get() to make that request and use $scope.apply() in the response handlers.
The usage of If-Modified-Since = "0" header breaks Tomcat (Problem with parsing header date, as 0 is not valid value RFC). Fixed using value Mon, 26 Jul 1997 05:00:00 GMT instead.
I didn't use the "If-Modified-Since" header and it worked without that. Just the other two are necessary.
C
Community

You can either append a unique querystring (I believe this is what jQuery does with the cache: false option) to the request.

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

A perhaps better solution is if you have access to the server, then you can make sure that necessary headers are set to prevent caching. If you're using ASP.NET MVC this answer might help.


$http.get(url+ "?"+new Date().toString()) is just another representation, without using parameter but adding it to query string.
d
dillip

you may add an 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;
               }
           };
    });

you should remove console.log lines after verifying.


And you should be using $log in case you forget to take them out.
I am having serious caching problems in IE, which leads to a blank page, because important parts didn't execute. Using the propsed interceptor solved this problem! +1
I think this is the best approach, since it avoids issues with CORS and IE's behavior of triggering a preflight request if you add additional headers. This seems to be the safest method to not run into additional problems
@dilip pattnaik:- Why this issue occurs with angular and ie ?
H
Hiro

I simply added three meta tags into index.html on angular project, and cache issue was solved on 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">

We already had those meta tags in our index.html when we noticed IE11 was caching AJAX requests :/ But configuring $httpProvider as shown in other answers worked fine.
V
Vitaliy Ulantikov

Duplicating my answer in another thread.

For Angular 2 and newer, the easiest way to add no-cache headers by overriding 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'
    });
}

And reference it in your module:

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

Wouldn't those be headers for the server response, not for the browser request? (I could imagine one could set If-Modified-Since with some date far in the past using the above method.)
@Vitaliy:- Why this issue occurs with angular and ie ?
Your approach will remove any custom headers that are already there. Hence do the following instead of creating a new Header object. headers: req.headers .set('Cache-Control', 'no-cache') .set('Pragma', 'no-cache') .set('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT')
m
marksyzm

The guaranteed one that I had working was something along these lines:

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

I had to merge 2 of the above solutions in order to guarantee the correct usage for all methods, but you can replace common with get or other method i.e. put, post, delete to make this work for different cases.


can you tell me where in the code you have added this to the angular.js file? what line #?
@JonathanScialpi I updated it to show where I might put it. Where it is within the anonymous function shouldn't matter.
@marksyzm can u plzz tell me what is the meaning of this line if (!$httpProvider.defaults.headers.get) { $httpProvider.defaults.headers.common = {}; }
@MonojitSarkar Ah, that was supposed to be headers.common in the if statement, thanks for that pointer
["If-Modified-Since"] = "0" is illegal and with generate a Bad Request on some back ends. it should be a date.
y
yamaxim

This only line helped me (Angular 1.4.8):

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

UPD: The problem is IE11 does aggressive caching. When I was looking into Fiddler I noticed that in F12 mode requests are sending "Pragma=no-cache" and endpoint is requested every time I visit a page. But in normal mode endpoint was requested only once at the first time when I visited the page.


Just FYI, this answer caused a CORS issue when requesting files from Azure's blob storage, difficult to track down but eventually figured out this was the cause. Removing the pragma header fixed my CORS issue (but re-instated the IE caching issue).
R
Razan Paul

To avoid caching, one option is to give different URL for the same resource or data. To generate different URL, you can add a random query string to the end of the URL. This technique works for JQuery, Angular or other type ajax requests.

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

k
khichar.anil

I get it resolved appending datetime as an random number:

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

:- Why this issue occurs with angular and ie ?
C
Community

Solution above will work (make the url unique by adding in the querystring a new param) but I prefer the solution propose [here]: Better Way to Prevent IE Cache in AngularJS?, which handle this at server level as it's not specific to IE. I mean, if that resource should not be cached, do it on the server (this as nothing to do with the browser used; it's intrisic to the resource).

For example in java with JAX-RS do it programatically for JAX-RS v1 or declativly for JAX-RS v2.

I'm sure anyone will figure out how to do it


Although it can be elaborated, this is the proper way of doing it. The client side should not be choosing what to cache or not, but it should be the server who should tell the client what needs to be cached or not.
I fully agree, this must be a proper way
J
Jens Alenius

This is a little bit to old but: Solutions like is obsolete. Let the server handle the cache or not cache (in the response). The only way to guarantee no caching (thinking about new versions in production) is to change the js or css file with a version number. I do this with webpack.


N
No Name

also you can try in your servce to set headers like for example:

...
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")                   
    }
}
....

D
Dale K

The correct, server-side, solution: Better Way to Prevent IE Cache in AngularJS?

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

a
amadan

This issue is due to the IE caching problem as you said, you can test it in IE debug mode by pressing f12 (this will work fine in debug mode).IE will not take the server data in each time the page calls, it takes the data from cache. To disable this do either of the following:

append the following with your http service request url

//Before (issued one)

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

//After (working fine)

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

disable the cache for the entire Module :-

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


D
Danila Ganchar
meta http-equiv="Cache-Control" content="no-cache"

I just added this to View and it started working on IE. Confirmed to work on Angular 2.


D
Dale K

An option is to use the simple approach of adding a Timestamp with each request no need to clear cache.

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

M
Mayank Parnami

Try this, it worked for me in a similar case:-

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