Angular 使用拦截器和retrywhen对特定错误进行HTTP请求重试

Angular 使用拦截器和retrywhen对特定错误进行HTTP请求重试,angular,interceptor,retrywhen,Angular,Interceptor,Retrywhen,我有一个服务,它调用获取API并接收响应。我已经实现了HTTP拦截器,以便在整个应用程序中正确、全局地处理任何错误。我想做的是,当我的API返回一个特定的错误时,例如,错误501,我需要在每个请求之前重试该请求n次,延迟t秒。如果重试结束,我还希望处理一般错误(即,如果上次重试时出错,我希望以特定方式处理)。请帮我弄清楚如何解决这个问题 这一切都是用Angular 6实现的,语法正确的解决方案将受到赞赏 谢谢 < p>您可以考虑使用 Rebug时,,延迟< /代码>, TAP ,扫描< /C>

我有一个服务,它调用获取API并接收响应。我已经实现了HTTP拦截器,以便在整个应用程序中正确、全局地处理任何错误。我想做的是,当我的API返回一个特定的错误时,例如,错误501,我需要在每个请求之前重试该请求n次,延迟t秒。如果重试结束,我还希望处理一般错误(即,如果上次重试时出错,我希望以特定方式处理)。请帮我弄清楚如何解决这个问题

这一切都是用Angular 6实现的,语法正确的解决方案将受到赞赏


<>谢谢

< p>您可以考虑使用<代码> Rebug时,,<代码>延迟< /代码>,<代码> TAP ,<代码>扫描< /C> > RXJS。类似于下面的代码,Angular服务调用Google API对不在浏览器上运行的应用(例如桌面应用)中的用户进行身份验证。此服务使用RxJS以特定的间隔重试REST API调用,以防由于不稳定的internet连接而失败:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { retryWhen, delay, tap, scan, concatMap } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class GoogleDeviceAuthService {

  private readonly client_id = "<client-id>";
  private readonly client_secret = "<client-secret>";

  private readonly userCodeRequest = {
    "client_id": this.client_id,
    "scope": "email profile"
  };

  private readonly pollGoogleAuthServerRequestTemplate = {
    "client_id": this.client_id,
    "client_secret": this.client_secret,
    "code": "",
    "grant_type": "http://oauth.net/grant_type/device/1.0"
  }

  private readonly userCodeUrl = "https://accounts.google.com/o/oauth2/device/code";

  private readonly pollGoogleAuthServerUrl = "https://www.googleapis.com/oauth2/v4/token";

  constructor(private readonly http: HttpClient) { }

  public getUserCode() {
    return this.http.post(this.userCodeUrl, this.userCodeRequest)
      .pipe(
        retryWhen(err => err.pipe(
          scan(
            (retryCount, err) => {
              if (retryCount > 3)
                throw err;
              else
                return retryCount + 1;
            }, 0
          ),
          delay(1000),
          tap(err => console.log("Retrying...", err))
        )));
  }

  public checkAuthServerForUserInput(deviceCode) {
    let pollGoogleAuthServerRequest = { 
        ...this.pollGoogleAuthServerRequestTemplate, 
        ...{ "code": deviceCode } };
    return this.http.post(this.pollGoogleAuthServerUrl, pollGoogleAuthServerRequest)
      .pipe(
        retryWhen(err => err.pipe(
          scan(
            (retryCount, err) => {
              if (retryCount > 3)
                throw err;
              else
                return retryCount + 1;
            }, 0
          ),
          delay(1000),
          tap(err => console.log("Retrying...", err))
        )));;
  }
}
从'@angular/core'导入{Injectable};
从'@angular/common/http'导入{HttpClient};
从“rxjs/operators”导入{retryWhen、delay、tap、scan、concatMap};
@注射的({
providedIn:'根'
})
导出类GoogleDeviceAuthService{
私有只读客户端_id=“”;
私有只读客户端_secret=“”;
私有只读userCodeRequest={
“客户id”:这个.client\u id,
“范围”:“电子邮件配置文件”
};
私有只读pollGoogleAuthServerRequestTemplate={
“客户id”:这个.client\u id,
“客户秘密”:这是客户秘密,
“代码”:“,
“授权类型”:http://oauth.net/grant_type/device/1.0"
}
私有只读userCodeUrl=”https://accounts.google.com/o/oauth2/device/code";
私有只读pollGoogleAuthServerUrl=”https://www.googleapis.com/oauth2/v4/token";
构造函数(私有只读http:HttpClient){}
公共getUserCode(){
返回this.http.post(this.userCodeUrl,this.userCodeRequest)
.烟斗(
retryWhen(err=>err.pipe(
扫描(
(retryCount,err)=>{
如果(retryCount>3)
犯错误;
其他的
返回retryCount+1;
}, 0
),
延迟(1000),
轻触(err=>console.log(“重试…”,err))
)));
}
公共检查AuthServerForUserInput(deviceCode){
让pollGoogleAuthServerRequest={
…此.pollGoogleAuthServerRequestTemplate,
…{“代码”:设备代码};
返回此.http.post(this.pollGoogleAuthServerUrl,pollGoogleAuthServerRequest)
.烟斗(
retryWhen(err=>err.pipe(
扫描(
(retryCount,err)=>{
如果(retryCount>3)
犯错误;
其他的
返回retryCount+1;
}, 0
),
延迟(1000),
轻触(err=>console.log(“重试…”,err))
)));;
}
}

您认为这会覆盖我实现的拦截器吗?另外,我看到您使用count变量进行重试,我们可以改用retry()方法吗?@KalyaniShirwalkar-这与拦截器无关。因此,拦截器逻辑应该像往常一样工作<代码>重试当此处使用方法时。我希望有一个延迟,同时重试一个固定的次数。我找不到比这更好的办法了。也许有一个更好的方法我现在还不知道。事实上,有没有一种方法可以把它缩小到一个错误而不是全部?我尝试使用error.status,但error的类型是ProgressEvent,它没有status属性。@KalyaniShirwalkar我很快就会回来。但是如果您很匆忙,您可能需要
console.log
error对象并查看哪个字段包含状态。如果状态不是您想要的,则立即抛出错误。