【问题标题】:Angular, error interceptor, retry the original request on different urlAngular,错误拦截器,在不同的 url 上重试原始请求
【发布时间】:2019-09-21 23:28:46
【问题描述】:

几个月前我开始在一个新项目上使用 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 函数中迭代?

提前致谢!

【问题讨论】:

  • 为什么不在后端服务器之前使用负载均衡器?
  • @talhature,用户可以通过下拉菜单更改 API url。所以我想自动使用相同的逻辑。

标签: angular error-handling rxjs observable angular7


【解决方案1】:

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

为此,您可以在 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

【讨论】:

  • 谢谢。您的解决方案很好解决了ping问题。但是其余的逻辑仍然不起作用。请求不会重试。在这种情况下我应该标记你的答案吗?
  • 我会将此答案标记为正确,因为它解决了我的问题,但我的代码仍然存在一些问题。也许我会写另一个问题。再次感谢!
猜你喜欢
  • 2020-12-14
  • 1970-01-01
  • 2020-02-12
  • 2019-01-04
  • 2020-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-10
相关资源
最近更新 更多