【问题标题】:Angular IE Caching issue for $http$http 的 Angular IE 缓存问题
【发布时间】:2013-04-12 11:33:21
【问题描述】:

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

【问题讨论】:

    标签: javascript caching angularjs


    【解决方案1】:

    我没有为每个单独的 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';
    }]);
    

    【讨论】:

    • If-Modified-Since 标头使 IIS+iisnode 对通过 ngIncludengView 加载的每个 html 文件抛出 400 Bad Request。以下两个标题为我解决了这个问题(我从没有缓存问题的 Chrome 中提取了它们):$httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache';$httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
    • 在我看来,这个答案应该被标记为答案,虽然 Martin 提供的解决方案确实有效,但它更像是一种 hack,而不是实际的修复。
    • 这适用于我的本地 GET 请求,但它导致我发出的一个 CORS 请求开始使用 OPTIONS 方法而不是 GET 方法。第 3 方服务器不支持 OPTIONS 方法,所以我的解决方法是使用 jQuery.get() 发出请求并在响应处理程序中使用 $scope.apply()。
    • 使用If-Modified-Since = "0" 标头会破坏Tomcat(解析标头日期的问题,因为0 不是有效值RFC)。改用值Mon, 26 Jul 1997 05:00:00 GMT 修复。
    • 我没有使用“If-Modified-Since”标头,没有它也可以工作。只需要另外两个。
    【解决方案2】:

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

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

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

    【讨论】:

    • $http.get(url+ "?"+new Date().toString()) 只是另一种表示形式,没有使用参数,而是将其添加到查询字符串中。
    【解决方案3】:

    你可以添加一个拦截器。

    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,以防你忘记把它们拿出来。
    • 我在 IE 中遇到严重的缓存问题,导致出现空白页,因为重要部分没有执行。使用 propsed 拦截器解决了这个问题! +1
    • 我认为这是最好的方法,因为它避免了 CORS 问题和 IE 在添加其他标头时触发预检请求的行为。这似乎是不会遇到其他问题的最安全方法
    • @dilip pattnaik:- 为什么 Angular 和 ie 会出现这个问题?
    【解决方案4】:

    我只是在angular项目的index.html中添加了三个meta标签,缓存问题在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">
    

    【讨论】:

    • 当我们注意到 IE11 正在缓存 AJAX 请求时,我们在 index.html 中已经有了这些元标记:/ 但是按照其他答案所示配置 $httpProvider 效果很好。
    【解决方案5】:

    复制my answer in another thread

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

    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 设置为过去的某个日期。)
    • @Vitaliy:- 为什么 Angular 和 ie 会出现这个问题?
    • 您的方法将删除任何已经存在的自定义标头。因此,请执行以下操作,而不是创建新的 Header 对象。 headers: req.headers .set('Cache-Control', 'no-cache') .set('Pragma', 'no-cache') .set('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT')
    【解决方案6】:

    我工作的保证是这样的:

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

    为了保证所有方法的正确使用,我必须合并上述解决方案中的 2 个,但您可以将 common 替换为 get 或其他方法,即 putpostdelete 到使其适用于不同的情况。

    【讨论】:

    • 您能告诉我您在代码中的哪个位置将它添加到 angular.js 文件中吗?哪一行#?
    • @JonathanScialpi 我更新了它以显示我可能把它放在哪里。它在匿名函数中的位置无关紧要。
    • @marksyzm 你能告诉我这行是什么意思吗if (!$httpProvider.defaults.headers.get) { $httpProvider.defaults.headers.common = {}; }
    • @MonojitSarkar 啊,这应该是 if 语句中的 headers.common,谢谢你的指点
    • ["If-Modified-Since"] = "0" 是非法的,并且会在某些后端生成错误请求。它应该是一个日期。
    【解决方案7】:

    这一行对我有帮助(Angular 1.4.8):

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

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

    【讨论】:

    • 仅供参考,当从 Azure 的 blob 存储请求文件时,此答案导致 CORS 问题,难以追踪,但最终发现这是原因。删除 pragma 标头修复了我的 CORS 问题(但恢复了 IE 缓存问题)。
    【解决方案8】:

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

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

    【讨论】:

      【解决方案9】:

      我解决了将日期时间附加为随机数:

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

      【讨论】:

      • :- 为什么 angular 和 ie 会出现这个问题?
      【解决方案10】:

      上面的解决方案将起作用(通过在查询字符串中添加一个新参数使 url 唯一)但我更喜欢提出的解决方案 [此处]:Better Way to Prevent IE Cache in AngularJS?,它在服务器级别处理此问题,因为它不是特定于 IE 的。我的意思是,如果不应该缓存该资源,请在服务器上执行(这与所使用的浏览器无关;它是资源固有的)。

      例如,在带有 JAX-RS 的 java 中,programatically 用于 JAX-RS v1 或 declativly 用于 JAX-RS v2。

      我相信任何人都会想办法做到这一点

      【讨论】:

      • 虽然可以细化,但这是正确的做法。客户端不应该选择缓存或不缓存什么,而应该是服务器应该告诉客户端什么需要缓存。
      • 我完全同意,这一定是正确的方式
      【解决方案11】:

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

      【讨论】:

        【解决方案12】:

        您也可以尝试在您的服务中设置标题,例如:

        ... 从“@angular/core”导入{可注入}; 从“@angular/common/http”导入 { HttpClient、HttpHeaders、HttpParams }; ... @Injectable() 导出类 MyService { 私有标头:HttpHeaders; 构造函数(私有http:HttpClient ..) { this.headers = 新的 HttpHeaders() .append("内容类型", "应用程序/json") .append("接受", "应用程序/json") .append("LanguageCulture", this.headersLanguage) .append("缓存控制", "无缓存") .append("Pragma", "no-cache") } } ……

        【讨论】:

          【解决方案13】:

          正确的服务器端解决方案:Better Way to Prevent IE Cache in AngularJS?

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

          【讨论】:

            【解决方案14】:

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

            1. 在您的 http 服务请求 url 中附加以下内容

            //之前(发出一个)

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

            //之后(工作正常)

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

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

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

            【讨论】:

              【解决方案15】:
              meta http-equiv="Cache-Control" content="no-cache"
              

              我刚刚将它添加到 View 并开始在 IE 上运行。确认可以在 Angular 2 上工作。

              【讨论】:

                【解决方案16】:

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

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

                【讨论】:

                  【解决方案17】:

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

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

                  【讨论】:

                    猜你喜欢
                    • 2019-07-13
                    • 2011-02-24
                    • 2013-12-11
                    • 1970-01-01
                    • 2011-09-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2014-03-06
                    • 1970-01-01
                    相关资源
                    最近更新 更多