首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在angular 6中重试HTTP请求

在angular 6中重试HTTP请求
EN

Stack Overflow用户
提问于 2018-08-18 14:35:11
回答 2查看 19.1K关注 0票数 6

我使用拦截器根据每个请求的HTTP响应显示错误消息。

代码语言:javascript
运行
复制
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const customReq = request.clone({
        //headers: request.headers.set('app-language', 'en')
    });
    return next
        .handle(customReq).pipe(
            tap((ev: HttpEvent<any>) => {
                if (ev instanceof HttpResponse) {
                    // processing request
                }
            }),
            catchError(response => {
                if (response instanceof HttpErrorResponse) {
                    switch (response.status) {
                        case 0:
                            // server API connection error show
                            break;
                        case 403:
                            // error Token Invalid and Redirect to logout
                            break;
                        case 401:
                            // error Token Invalid and Redirect to logout
                            break;
                        case 502:
                            // Bad gateway error
                            break;
                        case 500:
                            // internal server error
                            break;
                    }
                }
                // return next.handle(request);
                return observableThrowError(response);
            })
        );
}

在我的项目中,web服务器在某些情况下可能会有一秒钟不可用,并回复500错误代码。我不希望我的web应用程序在收到错误后立即显示错误消息,我希望它在延迟一秒的情况下重试请求几次。

我已经尝试了rxjs重试:

代码语言:javascript
运行
复制
...
.handle(customReq).pipe(retry(5),
...

它没有用,因为它没有延迟。基于这个答案How to create an RXjs RetryWhen with delay and limit on tries

我尝试过retryWhen,如下所示:

代码语言:javascript
运行
复制
.handle(customReq).pipe(
    tap((ev: HttpEvent<any>) => {
        if (ev instanceof HttpResponse) {
            console.log('###processing response', ev, this.location);
        }
    }),
    retryWhen(error => {
        return error
            .flatMap((error: any) => {
                if (error.status  == 400) {
                    return Observable.of(error.status).delay(1000);
                }
                if (error.status  == 0) {
                    return observableThrowError(error).delay(1000);
                }
                return observableThrowError(error);
            })
            .take(5)
            .concat(observableThrowError(error));
    }),

但它并没有像预期的那样工作,也没有进入if条件。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-08-18 18:17:18

您的代码中有几个错误:

  1. 你正在隐藏error变量--首先它是一个错误流,然后它是一个错误对象。
  2. 使用observableThrowErrordelay没有任何效果。Error将绕过除处理error的运算符以外的所有运算符。
  3. 您正在混合"pipe(operator())“样式运算符和原型样式运算符.operator()

我提出了一些修改建议:

代码语言:javascript
运行
复制
.handle(customReq).pipe(
    tap((ev: HttpEvent<any>) => {
        if (ev instanceof HttpResponse) {
            console.log('###processing response', ev, this.location);
        }
    }),
    retryWhen(errors => errors
        .pipe(
            concatMap((error, count) => {
                if (count < 5 && (error.status == 400 || error.status == 0)) {
                    return Observable.of(error.status);
                }

                return observableThrowError(error);
            }),
            delay(1000)
        )
    ),

主要的变化是通过concatMap的第二个参数来跟踪错误计数,而不是使用take运算符,这主要用于取消订阅可观察对象,我认为您希望抛出一个错误。

票数 14
EN

Stack Overflow用户

发布于 2020-01-08 22:54:16

您可以使用重试操作符,最好在拦截器上使用它

代码语言:javascript
运行
复制
 intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(request)
        .pipe(retry(RETRY_NUMBER))

它只会在请求失败时重试,然后为了识别错误,您可以抛出一个错误,然后捕获它

代码语言:javascript
运行
复制
.pipe(tap(event => {
            // tipo http
            if (event instanceof HttpResponse) {
                if (event.body && event.body.error === true && event.body.errorMessage) {
                    throw new Error(event.body.errorMessage);
                }
            }
        }))


.pipe(catchError((err) => {

      if (err.status === 0) {
          //do something
      }
      // other conditions ...

      return EMPTY;
}));

不要忘记返回EMPTY,因为拦截器需要返回一个可观察的

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51905963

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档