Angular 7 Cache API results

5.1k views Asked by At

I've been struggling with the following: I have an angular-based ionic app and I`m struggling to cache the results for offline use. I don't (necessarily) need the online/offline check as I think I can manage that on my own.

Injectable/Post provider

import { Http, Headers, RequestOptions } from "@angular/http";
import "rxjs/add/operator/map";
//import {Observable,of, from } from 'rxjs';

@Injectable()
export class PostProvider {
  //private records$: Observable<Record[]>;
  server: string = "https://server/api_endpoint/";

  constructor(public http: Http) {}

  postData(body, file) {
    let type = "application/json; charset=UTF-8";
    let headers = new Headers({ "Content-Type": type });
    let options = new RequestOptions({ headers: headers });

    return this.http
      .post(this.server + file, JSON.stringify(body), options)
      .map(res => res.json());
  }
}

Component

In the component, I'm using the aksi for CRUD instructions towards the API

  loadCustomer() {


    return new Promise(resolve => {
      let body = {
        aksi: "getdata",
        user: this.username
      };

      this.postPvdr.postData(body, "proses-api.php").subscribe(
        data => {
          for (let customer of data.result) {
            //this.customers.push(customer);
            this.logn = customer.nume;
            this.logn = customer.pret;
            this.comis = customer.comis +' %';
            this.rhg = customer.rhg;
            this.pdg = customer.pdg;
            this.ptg = customer.ptg;
            this.defaultList.push(customer);
          }

//defaultList is used to serve up the data into an autocomplete field

          this.completeTestService.customerList = this.defaultList;
          resolve(true);
        },
  );
    });
  }

I'm ultranew to angular so I've barely understood the concept of Observables from quickreads. I've tried building it with $cacheFactory, got overwhelmed. Followed a video on how to do it but it ended up being for previous angular versions. Stumbled upon this

image

And when I tried to implement it got Generic type 'Record' requires 2 type argument(s)

If the code takes too much to write, any example of how this should work or (clear) documentation would be a blessing. After spending hours on this I'm at a point where I just feel stupid.

2

There are 2 answers

0
g0rb On

The Angular docs provide some examples on how to cache http requests using an interceptor. There is no provided caching service, so you will need to create your own service for this.

Below is one of their snippets on how to cache http requests in Angular.

@Injectable()
export class CachingInterceptor 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) : 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.
 */
function 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.
      }
    })
  );
}

Make sure to provide the interceptor in the module you plan to use it in.

0
Neo Liu On

I created a npm package for easily fetching and caching GET responses, and it is easy to config. ngx-http-get-shell. No need to create service.ts, and amend component.ts files, all you need is just include the shell component in 'component.html' and setup a maxStale value.

<ngx-http-get-shell [url]="url" [maxStale]="1000" [templateRef]="tmpl">
  <ng-template #tmpl let-data>
    <!-- YOUR USAGE OF DATA -->
  </ng-template>
</ngx-http-get-shell>