Angular HttpInterceptor - 处理异步响应

时间:2018-04-10 08:05:44

标签: angular asynchronous indexeddb angular-http-interceptors

我正在编写使用IndexedDB缓存数据的Angular应用程序。

每当应用程序即将对服务器进行特定的http调用时 我想从IndexedDB中检索这些数据,并从服务器中丰富或替换响应。

问题是从IndexedDB检索数据是异步操作,它返回Observable,我无法将修改后的数据返回给调用服务。

拦截器看起来像这样:

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);
  });
}

请在https://stackblitz.com/edit/angular-owqgb6

查看问题示例

2 个答案:

答案 0 :(得分:3)

你需要在map运算符中返回一些东西(在异步的回调函数中返回值,并且真正将它们返回到外部函数)。此外,当您检索异步结果以替换原始HttpResponse时,您可以将map更改为mergeMap运算符并在其中返回Observable。

尝试使用以下代码示例:

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);
});

修正 demo

答案 1 :(得分:0)

您可以执行以下操作:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  if (req.url.indexOf('https://api.someurl.com/') > -1) {
    let authReq: HttpRequest<any> = req;

    return this.authService.getCurrentSession().pipe(
      mergeMap(
        (session: Session) => {
          const token: string = session.getToken();
          authReq = req.clone({
            headers: req.headers.set('Authorization', token)
          });
          return next.handle(authReq);
        }
      ), 
      catchError(
        (error) => {
          console.error('Intercept error, couldn\'t add authorisation headers', error.message);
          next.handle(authReq);
          return of(error);
        }
      )
    );
  } else {
    return next.handle(req);
  }
}