-1

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, next: HttpHandler): Observable> { // 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(null);

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

if (!cached) {
  return undefined;
}

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

}

addToCache(req: HttpRequest, response: HttpResponse): void { const url = req.url; 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.

0

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, next: HttpHandler): Observable> { // 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(null);

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

if (!cached) {
  return undefined;
}

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

}

addToCache(req: HttpRequest, response: HttpResponse): void { const url = req.url; 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.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.