如何在用户点击按钮时通过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); } }) ); } }) ); } }
关键修改说明
- 异步逻辑转换:用
fromPromise把SweetAlert的异步弹窗转为Observable,确保拦截器返回的Observable会等待用户操作完成。 - 分支处理:通过
switchMap根据用户点击结果,要么重新发起请求(调用next.handle),要么抛出错误。 - 请求不可变性:使用
request.clone()创建请求副本,避免修改原始请求对象,符合Angular HTTP的设计规范。
内容的提问来源于stack exchange,提问作者simon777
相关产品推荐
相关产品推荐

