防止 IE11 在 Angular 2 中缓存 GET 调用

IT技术 javascript angular typescript internet-explorer-11 http-caching
2021-03-06 16:00:32

我有一个休息端点,它在 GET 调用中返回一个列表。我还有一个 POST 端点来添加新项目和一个 DELETE 来删除它们。这在 Firefox 和 Chrome 中有效,POST 和 DELETE 在 IE11 中有效。但是,IE11 中的 GET 仅适用于页面的初始加载。刷新返回缓存的数据。我在 Angular 1 中看到过关于这种行为的帖子,但在 Angular 2(候选版本 1)中没有看到。

6个回答

对于Angular 2 和更新版本,通过覆盖来添加无缓存标头的最简单方法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'
    });
}

module:

@NgModule({
    ...
    providers: [
        ...
        { provide: RequestOptions, useClass: CustomRequestOptions }
    ]
})
@cmaynard 我在研究如何为 Andular 设置全局缓存时遇到了你的问题,所以从谷歌的角度来看,你的措辞非常适合人们搜索的内容:)
2021-04-21 16:00:32
这是一个很好的解决方案,可以让来自 angular 请求的所有请求都没有缓存,但是我不希望所有请求都有这种行为,因为某些请求可以被缓存得很好。我去设置适当的标头服务器端。无论如何,我宁愿服务器具有缓存智能。我可能对这个问题措辞不当。
2021-05-01 16:00:32
是的,这很有效,谢谢。IE11的又一刺激!!
2021-05-02 16:00:32
这个解决方案对我不起作用,我不得不使用docs.netapp.com/sgws-110/手动禁用缓存...
2021-05-06 16:00:32
@cmaynard 我在考虑这个,也许选择是只向你的 Rest 服务提供这个 httpinterceptor。
2021-05-11 16:00:32

今天,我也遇到了这个问题,(该死的IE)。在我的项目中,我使用httpclient,那没有BaseRequestOptions我们应该用Http_Interceptor它来解决它!

import { HttpHandler,
    HttpProgressEvent,
    HttpInterceptor,
    HttpSentEvent,
    HttpHeaderResponse,
    HttpUserEvent,
    HttpRequest,
    HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';

export class CustomHttpInterceptorService implements HttpInterceptor {
    intercept(req: HttpRequest<any>, next: HttpHandler):
      Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
      const nextReq = req.clone({
        headers: req.headers.set('Cache-Control', 'no-cache')
          .set('Pragma', 'no-cache')
          .set('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT')
          .set('If-Modified-Since', '0')
      });

      return next.handle(nextReq);
  }
}

module提供

@NgModule({
    ...
    providers: [
        ...
        { provide: HTTP_INTERCEPTORS, useClass: CustomHttpInterceptorService, multi: true }
    ]
})
如果您使用 CORS,您可能需要Access-Control-Request-Headers在服务器端添加所有标头(Cache-Control、Pragma 等)否则你会遇到 CORS 问题。这意味着您的请求将失败。
2021-04-19 16:00:32
谢谢,这是 Angular 5 的正确答案。但是,由于我在原始问题中指定了 Angular 2,因此我会将该答案标记为对这个问题正确,请投赞成票!
2021-05-10 16:00:32

转发$http的 stackoverflow 响应Angular IE 缓存问题,您应该将标头“Pragma”、“no-cache”、“If-Modified-Since”添加到每个“GET”请求。

拦截器的场景不再支持 angular 2。所以你应该像这里描述的那样扩展 http什么是 angular2 中的 httpinterceptor 等价物?.

Angular 4.3 现在包含支持拦截器HttpClient服务。

编辑:请参阅下面的评论 - 这不是必需的(在绝大多数情况下)。

扩展上面 Jimmy Ho 的回答,我只想防止缓存我的 API 调用,而不是其他将从缓存中受益的静态内容。我所有的 API 调用都是针对包含“/api/”的 URL,所以我修改了 Jimmy Ho 的代码,检查只在请求的 URL 包含“/api/”时添加缓存头:

import { HttpHandler,
    HttpProgressEvent,
    HttpInterceptor,
    HttpSentEvent,
    HttpHeaderResponse,
    HttpUserEvent,
    HttpRequest,
    HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';

export class CustomHttpInterceptorService implements HttpInterceptor {
    intercept(req: HttpRequest<any>, next: HttpHandler):
    Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
    // Only turn off caching for API calls to the server.
    if (req.url.indexOf('/api/') >= 0) {
        const nextReq = req.clone({
            headers: req.headers.set('Cache-Control', 'no-cache')
                .set('Pragma', 'no-cache')
                .set('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT')
                .set('If-Modified-Since', '0')
        });

        return next.handle(nextReq);
    } else {
        // Pass the request through unchanged.
        return next.handle(req);
    }
}

}

HttpInterceptor 只影响通过 angular 的请求(所以在你的 Angular 服务中通常是 HttpClient),99% 的时间都是 API 调用。所以我不认为这个额外的检查是必要的。除非您出于某种原因在服务层内请求静态内容。
2021-04-22 16:00:32
@LambdaCruiser,是的,你说得对。这不是真的需要。我会把这个留在这里以防万一有人落入同样的陷阱。
2021-04-26 16:00:32

如上所述,您可以使用 http 请求拦截器来修改或设置请求的新标头。下面是一种在 http 请求拦截器上为更高版本的Angular版本(Angular 4+设置标头的更简单的方法这种方法只会设置或更新某个请求头。这是为了避免删除或覆盖一些重要的标头,如授权标头。

// cache-interceptor.service.ts
import { Injectable } from '@angular/core';
import {
  HttpInterceptor,
  HttpRequest,
  HttpHandler,
} from '@angular/common/http';

@Injectable()
export class CacheInterceptor implements HttpInterceptor {

  intercept(req: HttpRequest<any>, next: HttpHandler) {
    const httpRequest = req.clone({
      headers: req.headers
        .set('Cache-Control', 'no-cache')
        .set('Pragma', 'no-cache')
        .set('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT')
    })

    return next.handle(httpRequest)
  }
}

// app.module.ts

  import { HTTP_INTERCEPTORS } from '@angular/common/http'
  import { CacheInterceptor } from './cache-interceptor.service';

  // on providers
  providers: [{ provide: HTTP_INTERCEPTORS, useClass: CacheInterceptor, multi: true }]