首页 > 解决方案 > Angular Caching 通过拦截器变得简单,但不是针对每个请求,仅通过布尔值

问题描述

希望通过拦截器缓存请求,但不是针对每个请求。我需要一个标志来希望能够缓存与否

标签: angularcaching

解决方案


使用拦截器在 Angular 中实现缓存仅针对少数请求,而不是通过布尔值有条件地执行每个请求。

我一直在检查有关仅缓存少数请求而不是全部请求的在线解决方案。可悲的是,没有任何适合此目的的解决方案。因此,我决定编写一种非常简单的缓存方法来缓存特定请求。

这可以通过以下方式完成:

如下创建一个 cache.interceptor & cache.service 并将其添加到 app.module 的提供者中,如下所示:

providers:[
CacheService,
        { provide: HTTP_INTERCEPTORS, useClass: CachingInterceptor, multi: true }]

CachingInterceptor 代码:拦截器只会在它看到由进行 http 调用的服务设置的特定标头('cache-response')时缓存请求。

import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';

import { Observable } from 'rxjs/Observable';

// Add the service we created in Step 1
import { of } from 'rxjs';
import { tap } from 'rxjs/operators';
import { CacheService } from './cache.service';

@Injectable()
export class CachingInterceptor implements HttpInterceptor {

  constructor(private readonly cacheService: CacheService) {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // Don't cache if it's not a GET request
    if (req.method !== 'GET') {
      return next.handle(req);
    }

    // delete cache if no header is set by service's method
    if (!req.headers.get('cache-response')) {
      if (this.cacheService.cacheMap.get(req.urlWithParams)) {
        this.cacheService.cacheMap.delete(req.urlWithParams);
      }

      return next.handle(req);
    }

    // Checked if there is cached data for this URI
    const cachedResponse = this.cacheService.getFromCache(req);
    if (cachedResponse) {
      // In case of parallel requests to same URI,
      // return the request already in progress
      // otherwise return the last cached data
      return (cachedResponse instanceof Observable) ? cachedResponse : of(cachedResponse.clone());
    }

    // If the request of going through for first time
    // then let the request proceed and cache the response
    return next.handle(req)
        .pipe(tap(event => {
            if (event instanceof HttpResponse) {
                this.cacheService.addToCache(req, event);
            }
        }));
  }
}

CacheService 代码:此服务用于添加/从缓存中获取。

import { HttpRequest, HttpResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';

@Injectable()
export class CacheService  {
  cacheMap = new Map<any, any>(null);

  getFromCache(req: HttpRequest<any>): HttpResponse<any> | undefined {
    const url = req.urlWithParams;
    const cached = this.cacheMap.get(url);

    if (!cached) {
      return undefined;
    }

    return (this.cacheMap.get(url)).response;
  }

  addToCache(req: HttpRequest<any>, response: HttpResponse<any>): void {
    const url = req.url;
    const entry = { url, response, addedTime: Date.now() };
    this.cacheMap.set(url, entry);
  }
}

在您的服务中:

getMethod(int param1, cache = false): any {
    let headers: HttpHeaders;
    if (cache) {
      headers = new HttpHeaders({ 'cache-response': 'true' });
    }

    return this.http.get(
      'http://apiUrl',
      { headers }
    );
  }

就是这样。您有一个拦截器,它只缓存具有标头集的请求。


推荐阅读