HTTP请求使用拦截器重试特定错误,然后重试

时间:2018-11-14 02:52:07

标签: angular interceptor retrywhen

我有一个调用GET API并收到响应的服务。我已经实现了HTTP Interceptor,可以正确,全局地处理整个应用程序中的所有错误。我想做的是,当我的API返回特定错误(例如,错误501)时,我需要在每个请求之前重试该请求n次(无次数)和t秒的延迟。如果重试结束,我也想处理一个通用错误(即如果上次重试遇到错误,我想以一种特殊的方式处理它)。请帮我弄清楚如何解决这个问题。

所有这些都是使用Angular 6实现的,使用正确语法的解决方案将不胜感激。

谢谢

1 个答案:

答案 0 :(得分:1)

您可以考虑使用RxJS的retryWhendelaytapscan来执行此操作。例如以下代码,其中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))
        )));;
  }
}