Search code examples
angularcachingpromiserxjs

Attempting to cache HttpClient Request in Angular but seeing unresolved variables


I pretty much copied the code below from the Angular HttpClient Docs

The reason I want to cache HttpClient GETS is because the site makes multiple GET requests to an endpoint but the data only changes once a day. So I'm thinking I could just cache the requests and save some space/time. I do have a browser cache setup on my nginx server, but that doesn't cache client requests, correct?

It's telling me, isCachable, get and put are unresolved. Am I missing an import somewhere or is there something else?

import {Injectable} from '@angular/core';
import {HttpEvent, HttpHandler, HttpHeaders, HttpInterceptor, HttpRequest, HttpResponse} from '@angular/common/http';
import {of} from 'rxjs/observable/of';
import {Observable} from 'rxjs/Observable';

@Injectable()
export class RequestCacheManager implements HttpInterceptor {
  constructor(private cache: RequestCache) {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler) {
    // continue if not cachable.
    if (!isCachable(req)) {
      return next.handle(req);
    }

    const cachedResponse = this.cache.get(req);
    return cachedResponse ?
      of(cachedResponse) : this.sendRequest(req, next, this.cache);
  }

  /**
   * Get server response observable by sending request to `next()`.
   * Will add the response to the cache on the way out.
   */
  sendRequest(req: HttpRequest<any>,
              next: HttpHandler,
              cache: RequestCache): Observable<HttpEvent<any>> {

    // No headers allowed in npm search request
    const noHeaderReq = req.clone({headers: new HttpHeaders()});

    return next.handle(noHeaderReq).pipe(
      tap(event => {
        // There may be other events besides the response.
        if (event instanceof HttpResponse) {
          cache.put(req, event); // Update the cache.
        }
      })
    );
  }
}

I'm hoping to implement this to help cut down on the amount of client side time/requests and space neccasary for my App to function.


Solution

  • The documentation at angular.io/guide/http#caching doesn't currently give the full picture.

    This blog post is helpful.

    You need to implement the RequestCache, called RequestCacheWithMap in the example (and the example also depends on a MessageService).

    Then you provide the HttpInterceptor something like this:

    import { HTTP_INTERCEPTORS } from '@angular/common/http';
    import { MyInterceptor } from './http-interceptors/my-interceptor';
    import { RequestCacheWithMap } from './services/request-cache.service';
    import { MessageService } from './services/message.service';
    
    @NgModule({
      providers: [
        RequestCacheWithMap,
        MessageService,
        {
          provide: HTTP_INTERCEPTORS,
          useClass: MyInterceptor,
          multi: true,
        },
      ],
      bootstrap: [AppComponent]
    })
    export class AppModule { }