使用Http Interceptor进行Angular 6缓存-代码中的Map运算符以某种方式改变了缓存的HttpResponse

时间:2018-09-24 20:37:53

标签: angular caching angular-http-interceptors

最近,我使用HttpInterceptor在Angular 6应用程序中使用了一个缓存。它将响应记录在内存中,并在响应存在TTL的情况下为它们提供服务。但是我有一个问题,其中发出Http请求的程序代码使用map运算符来修改检索到的数据,因此以某种方式将其保存到缓存中。如何做到这一点,以便从服务器中检索到的HttpResponse对象从服务器检索并将它们存储在缓存后不会以任何方式发生突变?

我创建了一个演示该问题的堆栈闪电:

https://stackblitz.com/edit/angular-caching-mutation

从缓存中提供响应后,它将被拆分成一个数组,就像映射操作发生在将服务器响应保存到缓存中之前一样。

Fetcher服务进行HTTP调用并更改响应:

getData() {
return this.http.get('https://jsonplaceholder.typicode.com/todos/1')
  .pipe(map(next => {
    next['title'] = next['title'].split('u');
    return next;
  }));;
}

拦截器:

const TTL = 5;

@Injectable()
export class CacheInterceptor implements HttpInterceptor {
  constructor(private cache: GetCacheService) {
  }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (!(request.method === 'GET')) {
      return next.handle(request);
    } else {
      console.log('Checking cache for data.');
      const cachedResponse = this.cache.get(request.url);
      return cachedResponse ? of(cachedResponse) : this.handleRequest(request, next);
    }
  }

  private handleRequest(
    request: HttpRequest<any>,
    next: HttpHandler
  ) {
    return next.handle(request).pipe(tap(event => {

      if (event instanceof HttpResponse) {
        this.cache.set(request.url, event, TTL);
      }
    }));
  }
}

缓存服务:

@Injectable({
              providedIn: 'root'
            })
export class GetCacheService {
  private cache = new Map<string, [Date, HttpResponse<any>]>();

  constructor() {
  }

  get(key: string): HttpResponse<any> {
    const tuple = this.cache.get(key);
    if (!tuple) {
      return null;
    }

    const expires = tuple[0];
    const httpResponse = tuple[1];

    // check if cached HttpResponse is expired, if it is, delete
    // it and respond as if we had nothing cached
    const now = new Date();
    if (expires && expires.getTime() < now.getTime()) {
      this.cache.delete(key);
      return null;
    }
    console.log('Retrieved from cache!');
    console.log(httpResponse);
    console.log('The above cached HttpResponse object has been mutated by the mapping function in fetcher.service.ts');
    return httpResponse;
  }

  set(key: string, value: HttpResponse<any>, ttl = null) {
    if (ttl) {
      const expires = new Date();
      expires.setSeconds(expires.getSeconds() + ttl);
      this.cache.set(key, [expires, value]);
    } else {
      this.cache.set(key, [null, value]);
    }
    return true;
  }

}

1 个答案:

答案 0 :(得分:0)

内部缓存服务中的get()

您将返回引用相同对象实例的原始缓存对象,如果对其进行修改,它将被更改。您可以使用此代码

get(key: string): HttpResponse<any> {
   .....
   return Object.assign({}, httpResponse);
}