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

时间:2019-02-17 12:09:53

标签: angular typescript rxjs angular-httpclient angular-http-interceptors

我正在尝试使用拦截器来处理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 :(得分:3)

出于您的兴趣,我采用了您的方法并将其扩展了一点。

首先是创建一种自定义运算符:

<input type="file" id="fileinput" multiple />
<script type="text/javascript">
function readMultipleFiles(evt) {
//Retrieve all the files from the FileList object
var files = evt.target.files;
var Statement_Fname =[] ;
var statement_Month=[];
var statement_Year =[];
var statement_client=[];

    for (var i = 0, f; f = files[i]; i++) {
        Statement_Fname[i] = files[i].name
        var r = new FileReader();
            r.onload = (function (f) {
                                        return function (e) {
                                            var contents = e.target.result;
                                            var splt = contents.split(";")
                                            statement_Month[i] = splt[0];
                                                statement_year[i] = splt[1];
                                            statement_client[i] = splt[2]; 
                                            alert(contents);
                                                            };
                                    }   )(f);
                                        r.readAsText(f);
                                        }
}
document.getElementById('fileinput').addEventListener('change', 
readMultipleFiles, false);
</script>

然后您可以根据此运算符构造拦截器,如下所示:

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

您可以看到它在in this blitz上运行

答案 1 :(得分:0)

尝试以下代码。您应该反过来做。

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