Want to cache requests through interceptor but not for every requests. I need a flag to want to be able to cache or not
1 Answer
Implement Caching in Angular with interceptor only for a few requests & not every request conditionally through a boolean.
I have been checking for online solutions about caching only few requests and not all. Sadly there's not any apt solution for this purpose. Hence I decided to write one very simple Caching methodology to cache specific requests.
This can be done by below:
Create a cache.interceptor & cache.service like below and add it to the providers of app.module like so:
providers:[ CacheService, { provide: HTTP_INTERCEPTORS, useClass: CachingInterceptor, multi: true }] CachingInterceptor code: The interceptor will only cache requests when it sees a particular header('cache-response') set by your services that make the http call.
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 Code: This service is used to add/get from cache.
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.urlWithParams; const entry = { url, response, addedTime: Date.now() }; this.cacheMap.set(url, entry); } } In your services:
getMethod(int param1, cache = false): any { let headers: HttpHeaders; if (cache) { headers = new HttpHeaders({ 'cache-response': 'true' }); } return this.http.get( 'http://apiUrl', { headers } ); } And thats it. You have an interceptor that cache's only requests that have a header set.