Angular 8 Http 拦截器 return 值

Angular8 HttpInterceptor return value

我有一个基本的 HttpInterceptor,我在其中使用 rxjs retryWhen,以便在出现服务故障时重试一定次数。如果服务调用已达到最大重试次数,那么我想将其反馈给最初发起服务调用的方法。

我的问题是,我如何才能return 控制回 http 调用的原始发起者? 我需要这样做以便在一个地方(拦截器)集中控制处理重试,我希望能够回调到调用函数中的 success/failure 方法。

我的问题是错误被全局错误处理程序吞没了,没有任何内容返回给我的调用者。

示例:

this.MyServiceCall()
        .pipe(
          map((result) => {
            console.log('this is called when the service returns success');
          }),
         )
         // If there is an error, then how can I show it?
      })
    }


export class HttpRetryInterceptorService implements HttpInterceptor {
  constructor() { }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req).pipe(
        retryWhen(errors => errors
            .pipe(
            concatMap((err:HttpErrorResponse, count) => iif(
            () => (count < 3),
            of(err).pipe(
                map(()=>{
                    console.log(count.toString())
                }),
                delay((2 + Math.random()) ** count * 200)),
                throwError(err)
            ))
        ))
    );
  }
}

尝试使用 catchError()

this.MyServiceCall()
    .pipe(
        map((result) => {
            console.log('this is called when the service returns success');
        }),
        catchError((error) => {
            // Do something and return either an observable or rethrow the error
            return throwError(error);
        })
    );

https://www.learnrxjs.io/operators/error_handling/catch.html

我认为您可以使用 catchError 运算符。
您仍然可以在一个地方处理错误(即:您的拦截器)并通过 throwing an error in the observable 将错误委托给调用者您的服务将订阅

注意:如果在拦截器中使用throwError操作符,TS应该会报错:

intercept (req: HttpRequest<any>, next: HttpHandler) {
//~~~~~~ 
    const foo = false;

    return next.handle(req)
    .pipe(
      map(ev => foo ? ev : throwError('err!')),
    )
}

错误是:

Type Observable < never > is not assignable to type 'HttpEvent'.

并且 HttpEvent 类型如下所示:

export type HttpEvent<T> =
    HttpSentEvent | HttpHeaderResponse | HttpResponse<T>| HttpProgressEvent | HttpUserEvent<T>;

因此,那里不允许出现错误..但这是我在 this SO post.

中找到的解决方法
intercept (req: HttpRequest<any>, next: HttpHandler) {
    const foo = false;

    return next.handle(req)
      .pipe(
        map(e => {
          if (e instanceof HttpResponse && !foo) {
            throw new HttpErrorResponse({
              error: 'err'
            });
          }

          return e;
        })
    )
  }

现在,delegated 错误应该在您的服务的 catchError 回调中被捕获。

this.MyServiceCall()
    .pipe(
        map((result) => {
            console.log('this is called when the service returns success');
        }),
        catchError(err => {
            // Do something with this error...
        })
    )

编辑

拦截器抛出错误也可以通过这种方式实现:

intercept (req: HttpRequest<any>, next: HttpHandler) {
    const foo = false;

    return next.handle(req)
      .pipe(
      mergeMap(e => {
        if (!foo) {
          return throwError('err');
        }

        return of(e);
      }),
    )
  }

我错过了 throwError returns 可观察到的事实 :D.