0
votes

I'm attempting to leverage Angular 4.3+ HTTP_INTERCEPTORs to create a cache.

The idea that if the call's result has already been cached, it should push the cached result on the observable, and then continue with the http call.

This way, the user gets to see his data instantly if it's cached, so he can view it while the server is still retrieving the (potentially unchanged) data.

However, I don't know how to return an observable with an initial value that will get processed properly by the .subscribe.

For example:

someApi.get$(1).subscribe((result: any) => {
 console.log("Got result " + result);
});

...

// inside the interceptor
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  // whole bunch of logic
  let cachedResult = somethingRetrievedFromMyCache;
  // How do I "return" cachedResult?
  // Things I've tried:
  // .startWith(cachedResult)
  // Observable.of(cachedResult).concat(next.handle(request))
  return next.handle(request);
}

Expected scenario:

Got result [cachedResult]
Got result [newResult]

Thanks

1
What didn't work with Observable.of(cachedResult).concat(next.handle(request))? This looks correct to me.martin
@martin , this only triggered "Got result [newResult]".Aventil
Are you sure cachedResult wasn't empty?martin
See this stackblitz.com/edit/rxjs5-hnzwtt?file=index.ts (open console to see the result).martin
@martin Odd. The stackblitz example works fine, and the code is pretty much identical. cachedResult is not empty; it's a HTTPEvent (that's been converted to json and then parsed back again). Maybe Angular's HttpClient doesn't work as we might expect?Aventil

1 Answers

0
votes

It appears that interceptors is not the place to concat() Observables to one another. Ideologically this makes sense, as interceptors are moreso meant to transform a request.

I have found that concat() works as expected if I do it higher-level. Building on my example of the initial post:

someApi.get$(1).subscribe((result: any) => {
 console.log("Got result " + result);
});

// inside someApi
get$(id: int): Observable<T>{
  ... // caching logic
  let cachedResult = somethingRetrievedFromMyCache;
  if(cachedResult){
     return Observable.of(cachedResult).concat(this.httpClient.get<T>(url));
  }

  return this.httpClient.get<T>(url);
}

This works, subscribers get notified twice.

The inner workings of interceptors must be different than what I assumed, and are handling the observable being created differently than one would expect.