Недавно я получил кэш, работающий в приложении Angular 6 с использованием HttpInterceptor.Он записывает ответы в память и обслуживает их, если они существуют с TTL.Однако у меня есть проблема, когда программный код, который делает запросы Http, использует оператор карты для изменения полученных данных, это каким-то образом сохраняется в кэш.Как я могу сделать так, чтобы мои кэшированные объекты HttpResponse не были видоизменены каким-либо образом после извлечения их с сервера и сохранения их в кэше?
Я создал стек-блиц, который демонстрирует проблему:
https://stackblitz.com/edit/angular-caching-mutation
Когда ответ подается из кэша, он уже будет разбит на массив, как если бы операция отображения произошла до того, как ответ сервера был сохранен в кэше.
Служба получения, выполняющая 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;
}
}