如何在 Angular 6 中使用 HttpClient 禁用缓存

Posted

技术标签:

【中文标题】如何在 Angular 6 中使用 HttpClient 禁用缓存【英文标题】:How to disable caching with HttpClient get in Angular 6 【发布时间】:2018-11-09 19:47:50 【问题描述】:

我正在编写一个 Angular SPA 应用程序,它使用 HttpClient 从我的后端获取值。

告诉它不要缓存的简单方法是什么?我第一次询问它获取值时,它拒绝进行后续查询。

谢谢, 格里

【问题讨论】:

你也控制后端吗? 你能把这些请求的代码包括进来吗?还有组件模板,如果有的话,你使用的是什么后端框架? 据我所知你不能。我认为这是浏览器的功能。我听说过一些技巧,比如在 get 中添加一个随机整数,这样浏览器就会与之前的请求不匹配。否则我只是发布到我的 API。过去,缓存接听电话给我带来了很大的痛苦。 看起来您可以在请求中添加一些标头属性 -> ***.com/questions/37755782/… 根据其中一位评论者的说法,您似乎也可以控制此服务器端。 【参考方案1】:

使用元 html 标签,禁用浏览器缓存:-

<meta http-equiv="cache-control" content="no-cache, must-revalidate, post-check=0, pre-check=0">
<meta http-equiv="expires" content="0">
<meta http-equiv="pragma" content="no-cache">

或者,

http请求中添加headers为:-

headers = new Headers(
        'Cache-Control':  'no-cache, no-store, must-revalidate, post- 
                            check=0, pre-check=0',
        'Pragma': 'no-cache',
        'Expires': '0'
    );

【讨论】:

实际上我添加了一个 CustomHttpInterceptor 服务来为我所有的 http 请求执行此操作。 是的,将它添加到每个http请求的拦截器中是个好主意。【参考方案2】:

HTTPInterceptor 是修改应用程序中发生的 HTTP 请求的好方法。它充当一个可注入服务,可以在 HttpRequest 发生时调用。

HTTP 拦截器:

import  Injectable  from '@angular/core';
import  HttpInterceptor, HttpRequest, HttpHandler, HttpHeaders  from '@angular/common/http';

@Injectable()
export class CacheInterceptor implements HttpInterceptor 

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

    return next.handle(httpRequest);
  

使用拦截器:

import  NgModule  from '@angular/core';
import  BrowserModule  from '@angular/platform-browser';
import  FormsModule  from '@angular/forms';

import  AppComponent  from './app.component';

import  HttpClientModule, HTTP_INTERCEPTORS  from '@angular/common/http';
import  CacheInterceptor  from './http-interceptors/cache-interceptor';

@NgModule(
  imports:      [ BrowserModule, FormsModule ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ],
  providers: [
     provide: HTTP_INTERCEPTORS, useClass: CacheInterceptor, multi: true 
  ]
)
export class AppModule  

【讨论】:

我注意到这会阻止设置我的授权持有者令牌。有没有办法解决这个问题? @ronoc4 见angular.io/guide/http#setting-default-headers。您可以在同一个拦截器或单独的拦截器中设置身份验证令牌。示例: const authReq = req.clone( setHeaders: Authorization: authToken );【参考方案3】:

给网址加盐怎么样:

const salt = (new Date()).getTime();
return this.httpClient.get(`$url?$salt`,  responseType: 'text' );

同样的概念用于 html(css 或 js)中的静态资源链接来欺骗缓存。给url添加动态加盐会导致每次都重新加载target,因为url每次都不一样,但实际上是一样的。

/static/some-file.css?some-random-symbols

我使用日期是因为它保证我唯一的编号而不使用随机等。我们也可以为每个调用使用递增的整数。

上面提供的代码对我来说很好,以防我无法更改服务器配置。

【讨论】:

如果可能,请努力提供额外的解释,而不仅仅是代码。此类答案往往更有用,因为它们可以帮助社区成员,尤其是新开发人员更好地理解解决方案的推理,并有助于避免需要解决后续问题。 这是完美的。【参考方案4】:

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

// 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  HttpClientModule, HTTP_INTERCEPTORS  from '@angular/common/http'
  import  CacheInterceptor  from './cache-interceptor.service';

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

【讨论】:

这与@Pramod 的答案几乎完全相同 这对我有用,而不会覆盖其他标题。此外,您注意建议将每条指令存储在哪些文件中也很有帮助。

以上是关于如何在 Angular 6 中使用 HttpClient 禁用缓存的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Angular CLI 6: angular.json 中添加 Sass 编译?

如何使用添加按钮在 Angular 6 中上传多个文件?

如何在 Angular 6 中使用 HttpClient 禁用缓存

如何使用 Angular 6 中的类名更改背景颜色?

如何使用 RxJS 在 Angular 6 中发出一系列 http 请求

如何在节点脚本中重用 Angular 6 API 服务?