You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 11+全局实现API超时重试按钮方案咨询

实现方案:全局HTTP超时手动重试机制

核心思路

通过Angular HTTP拦截器结合RxJS操作符,实现全局API请求30秒超时检测;用Subject作为事件总线连接用户重试操作与请求重发逻辑,完全由用户手动触发重试,避免自动重试。

具体实现步骤

1. 构建重试状态管理服务

创建全局服务存储待重试请求、管理重试触发事件:

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class RetryService {
  private pendingRequest: HttpRequest<any> | null = null;
  private retryTrigger$ = new Subject<void>();

  setPendingRequest(req: HttpRequest<any>) {
    this.pendingRequest = req;
  }

  getPendingRequest() {
    return this.pendingRequest;
  }

  triggerRetry() {
    this.retryTrigger$.next();
  }

  getRetryStream() {
    return this.retryTrigger$.asObservable();
  }
}

2. 编写HTTP超时拦截器

在拦截器中处理超时逻辑,结合重试服务实现手动重发:

import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor,
  HttpErrorResponse
} from '@angular/common/http';
import { Observable, defer, throwError, timeout } from 'rxjs';
import { catchError, switchMap, tap } from 'rxjs/operators';
import { RetryService } from './retry.service';

@Injectable()
export class TimeoutRetryInterceptor implements HttpInterceptor {
  constructor(private retryService: RetryService) {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    return defer(() => {
      // 发起请求并设置30秒超时
      return next.handle(request).pipe(
        timeout(30000),
        catchError((error: HttpErrorResponse) => {
          // 捕获超时错误,存储请求并抛出提示
          if (error.name === 'TimeoutError') {
            this.retryService.setPendingRequest(request);
            return throwError(() => new Error('请求超时,请点击重试'));
          }
          // 其他错误直接抛出
          return throwError(() => error);
        })
      );
    }).pipe(
      // 监听重试触发事件,重发原请求
      switchMap(() => {
        return this.retryService.getRetryStream().pipe(
          switchMap(() => {
            const pendingReq = this.retryService.getPendingRequest();
            if (pendingReq) {
              return next.handle(pendingReq);
            }
            return throwError(() => new Error('无待重试请求'));
          }),
          // 重试完成后清空待请求
          tap(() => this.retryService.setPendingRequest(null))
        );
      })
    );
  }
}

3. 全局重试按钮组件

创建全局组件监听超时错误,显示重试按钮并触发重试:

import { Component } from '@angular/core';
import { RetryService } from './retry.service';
import { ErrorHandler } from '@angular/core';

@Component({
  selector: 'app-global-retry',
  template: `
    <div *ngIf="showRetryBtn" class="retry-modal">
      <p>请求超时,无法获取数据</p>
      <button class="retry-btn" (click)="handleRetry()">重试</button>
    </div>
  `,
  styles: [`
    .retry-modal {
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      padding: 24px;
      background: #fff;
      border-radius: 8px;
      box-shadow: 0 2px 12px rgba(0,0,0,0.15);
      z-index: 9999;
    }
    .retry-btn {
      padding: 8px 16px;
      margin-top: 12px;
      background: #1890ff;
      color: #fff;
      border: none;
      border-radius: 4px;
      cursor: pointer;
    }
  `]
})
export class GlobalRetryComponent {
  showRetryBtn = false;

  constructor(
    private retryService: RetryService,
    private errorHandler: ErrorHandler
  ) {
    // 覆盖全局错误处理,捕获超时提示
    const originalHandler = this.errorHandler.handleError;
    this.errorHandler.handleError = (error: any) => {
      if (error.message === '请求超时,请点击重试') {
        this.showRetryBtn = true;
      } else {
        originalHandler(error);
      }
    };
  }

  handleRetry() {
    this.showRetryBtn = false;
    this.retryService.triggerRetry();
  }
}

最后将该组件添加到根组件模板中,确保全局可见。

关键RxJS操作符说明

  • timeout: 直接设置请求超时阈值,超时后抛出TimeoutError。
  • defer: 延迟创建请求Observable,确保每次重试都是全新的请求实例,避免复用旧请求对象导致的异常。
  • switchMap: 监听重试触发的事件流,当用户点击按钮时,切换到新的请求Observable完成重发。
  • Subject: 作为事件总线,连接组件的点击操作与拦截器的请求重发逻辑,实现跨组件通信。

注意事项

  • 需在Angular模块的providers数组中注册拦截器,确保全局生效。
  • 可根据业务需求调整超时时间、错误提示文案及重试按钮样式。
  • 若需支持多并发请求的独立重试,可扩展RetryService存储请求队列,为每个请求分配唯一标识。

内容的提问来源于stack exchange,提问作者vishva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 06:02:04