typescript Angular - HTTP拦截器重试具有特定错误状态的请求?

wyyhbhjk  于 12个月前  发布在  TypeScript
关注(0)|答案(3)|浏览(161)

我尝试使用拦截器来处理http错误,并重试特殊的错误状态,在我的情况下,状态代码为502。

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(request)
      .pipe(
        retryWhen(errors => {
          return errors
            .pipe(
              mergeMap(error => (error.status === 502) ? throwError(error) : of(error)),
              take(2)
            )
        })
      )
  }

字符串
但是它不工作,而当我以这种方式使用retry()时,它工作得很好

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(request)
      .pipe(
        retry(2),
        catchError((error: HttpErrorResponse) => {
          return throwError(error);
        })
      )
  }

wfypjpf4

wfypjpf41#

我采用了你的方法,并扩大了一点,出于自己的利益。
第一个是创建一种自定义操作符:

import { timer, throwError, Observable } from 'rxjs';
import { mergeMap } from 'rxjs/operators';

export interface RetryParams {
  maxAttempts?: number;
  scalingDuration?: number;
  shouldRetry?: ({ status: number }) => boolean;
}

const defaultParams: RetryParams = {
  maxAttempts: 3,
  scalingDuration: 1000,
  shouldRetry: ({ status }) => status >= 400
}

export const genericRetryStrategy = (params: RetryParams = {}) => (attempts: Observable<any>) => attempts.pipe(
  mergeMap((error, i) => {
    const { maxAttempts, scalingDuration, shouldRetry } = { ...defaultParams, ...params }
    const retryAttempt = i + 1;
    // if maximum number of retries have been met
    // or response is a status code we don't wish to retry, throw error
    if (retryAttempt > maxAttempts || !shouldRetry(error)) {
      return throwError(error);
    }
    console.log(`Attempt ${retryAttempt}: retrying in ${retryAttempt * scalingDuration}ms`);
    // retry after 1s, 2s, etc...
    return timer(retryAttempt * scalingDuration);
  })
);

字符串
然后,您可以根据此操作符构造拦截器,如下所示:

@Injectable()
export class RetryInterceptor implements HttpInterceptor {
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const { shouldRetry } = this;
    return next.handle(request)
      .pipe(retryWhen(genericRetryStrategy({
        shouldRetry
      })));
  }

  private shouldRetry = (error) => error.status === 502;
}


你可以看到它的工作in this blitz

mzaanser

mzaanser2#

试试下面的代码。你应该反过来做。

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(request)
      .pipe(
        retryWhen(errors => {
          return errors
            .pipe(
              mergeMap(error=>error.status === 502?timer(0):throwError(error)),
              take(2)
            )
        }),
        catchError((error: HttpErrorResponse) => {
          return throwError(error);
        })
      )
  }

字符串

0kjbasz6

0kjbasz63#

我试图使用Jota的响应,但retryWhen现在已被弃用。所以我使用retry修改了他的响应。
这就是我得到的:

private readonly MAX_NUMBER_OF_RETRY_NO_CONNECTION: number = 5;
  private readonly RETRY_DELAY: number = 500;

  public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(request).pipe(
      retry({
        count: this.MAX_NUMBER_OF_RETRY_NO_CONNECTION,
        delay: (error: HttpErrorResponse, retryAttempt: number): Observable<number> => {
          // if maximum number of retries have been met
          // or response is a status code we don't wish to retry, throw error
          if (retryAttempt > this.MAX_NUMBER_OF_RETRY_NO_CONNECTION || error.status !== 404) {
            return throwError(() => error);
          }
          console.log(`Attempt ${retryAttempt}: retrying in ${retryAttempt * this.RETRY_DELAY}ms`);
          // retry after 1s, 2s, etc...
          return timer(retryAttempt * this.RETRY_DELAY);
        },
      }),
      catchError((error) => this.errorHandler(request, error))
    );
  }

  private errorHandler(request: HttpRequest<any>, error: HttpErrorResponse): Observable<HttpEvent<any>> {
    // Your usual error handler here....
  }

字符串

相关问题