首页 > 解决方案 > Angular,错误拦截器,在不同的 url 上重试原始请求

问题描述

几个月前我开始在一个新项目上使用 Angular,但现在我需要编写一个更复杂的错误拦截器,它可以检测后端 API 何时关闭。

拦截器需要检测 HTTP 错误代码,如果服务器关闭,我需要向第三方 API 服务器执行请求并获取可用后端服务器 URL 的列表,从该列表中 ping 每个服务器,直到找到一个 UP并重试原始请求(基本上是更改基本 URL)。

以下是拦截器需要执行的步骤:

  1. 检查错误代码,如果代码为0,则调用方法处理问题
  2. 向不同的 API 执行请求并获取所有可用服务器的列表
  3. 遍历列表并从该列表中 ping 每个服务器。
  4. 找到可用服务器后,重试原始请求。

就我而言,通常的要求是获取项目列表:

getProjects() {
    return this.http.get<IProject[]>('/projects');
  }

缺少基本 URL,因为我使用另一个拦截器动态添加它。

获取可用后端服务器 URL 列表的方法:

getRoutes() {
    return this.http.get<IRoute[]>(this.API_URL + '/routes');
  }

以及可以 ping 服务的服务

ping(url: string) {
    return this.http.get(url, { observe: 'response', responseType: 'text' });
  }

直到这里一切都按预期工作。

现在拦截器:

intercept(request, next) {
    return next.handle(request).pipe(
      catchError((error: any) => {
        if (error.status === 0) {
          return this.handleServerDownError(request, next);
        }
        return throwError(error);
      })
    );
  }

handleServerDownError(request, next) {
    return this.routesService.getRoutes().pipe(
      map(routes => {        
         routes.map((route: IRoute) =>
            this.pingService.ping(route.value).subscribe(res => {
              if (res.status === 200) {
                const updatedReq = request.clone({
                  url: route.value + request.url
                });
                return next.handle(updatedReq);
              }
            })
          );
      })
    );
  }

我几乎开始工作了,但是如果被 ping 的服务器关闭并且我收到相同的错误代码并且我进入无限循环,那么当然 ping 方法会返回相同的错误代码。

有什么想法让它工作吗?也许我可以改变 ping 方法返回不同的代码?

另外,在找到第一个可用服务器后,如何停止在 map 函数中进行迭代?

提前致谢!

标签: angularerror-handlingrxjsobservableangular7

解决方案


我几乎开始工作了,但是如果被 ping 的服务器关闭并且我收到相同的错误代码并且我进入无限循环,那么当然 ping 方法会返回相同的错误代码。

为此,您可以在 ping url 的末尾添加一个虚拟路径(例如:http://something:8080/dummy_ping),以便您可以识别它是否是 if 条件内的 ping 请求

if (error.status === 0 && !this.isDummyRequest(request)) {
  return this.handleServerDownError(request, next);
}
...
...

private isDummyRequest(request: HttpRequest<any>): boolean {
    if (request.url.includes('/dummy_ping')) {
      return true;
    } else {
      return false;
    }
}

另外,在找到第一个可用服务器后,如何停止在 map 函数中进行迭代?

可以选择使用 find 函数而不是 map


推荐阅读