1
votes

i am using Interceptors to cache and return the cached data as part of the Angular 4.3 HttpClient feature. Below is the utility service which is called from interceptor to store and return the HTTP Response.

@Injectable()
export class LocalStorageCacheService implements HttpCache {
    get(req: HttpRequest<any>): HttpResponse<any> {
        return <HttpResponse<any>>JSON.parse(localStorage.getItem(btoa(req.url)))
    };
    put(req: HttpRequest<any>, resp: HttpResponse<any>): void {
        localStorage.setItem(btoa(req.url), JSON.stringify(resp));
    }
}

Below is my interceptor which checks for cached entry and returns if available.

@Injectable()
export class CacheInterceptorService implements HttpInterceptor {
    constructor(private localStorageCacheService: LocalStorageCacheService) {
    }
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
      if (req.method !== 'GET') {
          return next.handle(req);
        }
        const cachedResponse = this.localStorageCacheService.get(req);
        if (cachedResponse) {
         **return Observable.of(cachedResponse);**
        }
        return next.handle(req).do(event => {
          if (event instanceof HttpResponse) {
            this.localStorageCacheService.put(req, event);
          }
        });
      }
}

The issue i am having is that, The http call is not hitting subscribe section of the calling component. i.e statement return Observable.of(cachedResponse); doesn't seems to be returning properly.

Any ideas?

Update #1

i figured out the problem, It was apparently casting from object to HttpResponse type not happening for some reason, So to prove that point, when i constructed the object manually using the plain object, it started to work. But obviously, manual casting is a dirty thing and need to figure out why casting wasn't working.

if (cachedResponse) {

  let httpResponse = new HttpResponse({
    status : cachedResponse.status,
    body : cachedResponse.body,
    headers : cachedResponse.headers,
    statusText : cachedResponse.statusText,
    url : cachedResponse.url
  });

  return Observable.of(httpResponse)
};
1

1 Answers

0
votes

Try like this :

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return <HttpRequest<any>>req.catch((error) => {
        return <HttpHandler>next.catch((err) => {
            if (req.method !== 'GET') {
                return next.handle(req);
            }
            const cachedResponse = this.localStorageCacheService.get(req);
            if (cachedResponse) {
                return Observable.throw(cachedResponse);
            }
            return next.handle(req).do(event => {
                if (event instanceof HttpResponse) {
                    this.localStorageCacheService.put(req, event);
                }
            });
        })
    })
}