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

如何在用户点击按钮时通过Angular Interceptor重试HTTP请求

Angular HttpInterceptor错误重试功能实现方案

当前代码的核心问题是:catchError中直接返回了throwError,而SweetAlert的弹窗是异步操作,此时Observable已完成并抛出错误,后续重试逻辑无法被订阅执行。要实现重试功能,需将弹窗逻辑转换为Observable,并根据用户操作决定重新发起请求或抛出错误。

解决方案步骤

  • 导入RxJS必要操作符:使用fromPromise将SweetAlert的Promise转为Observable,switchMap处理用户操作后的分支逻辑。
  • 重构catchError逻辑:不再直接返回错误,而是返回包含弹窗交互的Observable,等待用户操作后再执行对应逻辑。
  • 克隆请求:Angular的HttpRequest是不可变对象,重试时需使用clone()创建请求副本,这是HTTP请求处理的最佳实践。

修改后的完整代码

import { Injectable, Inject } from '@angular/core';
import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable, throwError, fromPromise } from 'rxjs';
import { catchError, switchMap } from "rxjs/operators";
import { AuthService } from '@auth0/auth0-angular';
import { DOCUMENT } from '@angular/common';
import Swal from 'sweetalert2'
import { NgxSpinnerService } from 'ngx-spinner';

@Injectable()
export class InterceptorService implements HttpInterceptor {

  constructor(
    @Inject(DOCUMENT) private document: Document,
    public auth: AuthService,
    public spinner: NgxSpinnerService,
  ) { }

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    return next.handle(request)
      .pipe(
        catchError((error: HttpErrorResponse) => {
          let errorMsg = '';
          // 401逻辑保持不变
          if (error.status === 401) {
            errorMsg = 'Unauthorized';
            this.auth.logout({
              returnTo: this.document.location.origin
            });
            return throwError(() => error);
          } else {
            errorMsg = `Error Code: ${error.status},  Message: ${error.message}`;
            // 将弹窗Promise转为Observable,处理用户操作
            return fromPromise(Swal.fire({
              text: `Error Encountered!`,
              confirmButtonText: 'Retry',
              confirmButtonColor: '#0f172a',
              cancelButtonText: 'Close',
              cancelButtonColor: '#f87171',
              showConfirmButton: true,
              showCancelButton: true
            })).pipe(
              switchMap((result) => {
                if (result.isConfirmed) {
                  // 克隆并重试请求
                  return next.handle(request.clone());
                } else {
                  // 用户关闭弹窗,抛出原始错误
                  return throwError(() => error);
                }
              })
            );
          }
        })
      );
  }
}

关键修改说明

  1. 异步逻辑转换:用fromPromise把SweetAlert的异步弹窗转为Observable,确保拦截器返回的Observable会等待用户操作完成。
  2. 分支处理:通过switchMap根据用户点击结果,要么重新发起请求(调用next.handle),要么抛出错误。
  3. 请求不可变性:使用request.clone()创建请求副本,避免修改原始请求对象,符合Angular HTTP的设计规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 16:46:29