Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular HttpInterceptor - Handle with async response

I am writing Angular application that uses IndexedDB to cache data.

Whenever the application is about to do specific http call to the server I would like to retrieve this data from the IndexedDB and enrich or replace the response from the server.

The problem is the that retrieving data from IndexedDB is Asynchronous operation that returns Observable and I am unable to return the modified data back to the calling service.

The Interceptor looks like this:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

  return next.handle(req).map((event) => {
    if (event instanceof HttpResponse) {
      console.log("before cacheResponseProccess");

      const val: Observable<HttpEvent<any>> = this.angularCache.cacheResponseProccess(event);

      val.subscribe(x => {
        console.log('Return modified response is:');
        console.log(x);
        return x;
      });
    }
  }).catch((error, caught) => {
    return Observable.throw(error);
  });
}

Please see sample of the issue at https://stackblitz.com/edit/angular-owqgb6

like image 214
Ronen Avatar asked Mar 07 '23 11:03

Ronen


1 Answers

You need to return things in map operator(returning values in callbacks of asynchronous won't really return them to outside function). Also, as you are retrieving asynchronous result to replace original HttpResponse, you can change map to mergeMap operator and return a Observable in it.

Try with below code example:

return next.handle(req).mergeMap((event) => {   // use mergeMap instead of map
  return new Observable(ob => {                 // return new Observable to retrieve asynchronous data
    if (event instanceof HttpResponse) {
      console.log("before cacheResponseProccess");

      const val: Observable<HttpEvent<any>> = this.angularCache.cacheResponseProccess(event);

      val.subscribe(x => {
        console.log('Return modified response is:', x);
        ob.next(x);         // return modified result
      });
    }
  });
}).catch((error, caught) => {
  return Observable.throw(error);
});

Fixed demo.

like image 121
Pengyy Avatar answered Mar 09 '23 06:03

Pengyy