Angular - HTTP-перехватчик для повторных запросов с определенным статусом ошибки? - PullRequest
0 голосов
/ 17 февраля 2019

Я пытаюсь использовать перехватчик для обработки ошибок 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);
        })
      )
  }

Ответы [ 2 ]

0 голосов
/ 17 февраля 2019

Я взял ваш подход и немного расширил его, исходя из собственных интересов.

Первым было бы создать своего рода пользовательский оператор:

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

Вы можете видеть, как он работает в этом блице

0 голосов
/ 17 февраля 2019

Попробуйте приведенный ниже код.Вы должны сделать это наоборот.

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