0

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

我的问题是,我怎样才能将控制权交还给 http 调用的原始发起者?我需要这样做以便在一个地方(拦截器)集中控制重试处理,并且我希望能够回调到调用函数中的成功/失败方法。

我的问题是错误被全局错误处理程序吞下,没有任何东西传回给我的调用者。

例子:

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

2 回答 2

0

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

注意:如果你throwError在拦截器中使用操作符,TS 应该抱怨这个:

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

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

错误是:

类型 Observable < never > 不可分配给类型“HttpEvent”。

HttpEvent类型如下所示:

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

因此,那里不允许出现错误。但这是我在此 SO 帖子中找到的解决方法。

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

现在,委托的错误应该在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我错过了返回可观察的事实:D。

于 2019-11-18T18:57:13.873 回答
0

尝试使用 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

于 2019-11-18T18:48:54.353 回答