Angular/Ionic HttpRequest拦截器:如何结合AlertController重复请求
嘿,我来帮你实现结合AlertController的请求重试功能!你的拦截器已经有了令牌注入和基础请求处理,只需要在错误流程里加入弹窗重试的逻辑就行,下面是具体的实现方案:
核心思路
我们会在拦截器的错误捕获流程中,针对可重试的错误(比如网络异常、服务器5xx错误、令牌过期等)弹出Alert提示用户选择是否重试;如果用户确认重试,就重新发起原请求。
完整代码实现
下面是补全后的拦截器代码,包含重试弹窗逻辑:
import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http'; import { Observable, of } from 'rxjs'; import { catchError, switchMap } from 'rxjs/operators'; import { AlertController } from '@ionic/angular'; import { Events } from '@ionic/angular'; import { AuthProvider } from './auth.provider'; @Injectable() export class RequestInterceptor implements HttpInterceptor { constructor( public injector: Injector, public alertCtrl: AlertController, public events: Events ) {} intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { let token = this.injector.get(AuthProvider).authToken; let request = req; // 保留你原来的令牌注入逻辑 if (token) { request = req.clone({ setHeaders: { Authorization: `Bearer ${token}` } }); } // 发起请求并处理错误重试 return next.handle(request).pipe( catchError((error) => { // 判断当前错误是否需要触发重试弹窗 if (!this.shouldTriggerRetry(error)) { return of(error); } // 弹出重试提示,根据用户选择决定是否重试 return this.presentRetryAlert().pipe( switchMap((userWantsRetry) => { if (userWantsRetry) { // 用户选择重试,重新发起请求 return next.handle(request); } // 用户取消,直接返回错误 return of(error); }) ); }) ); } // 自定义判断规则:哪些错误需要触发重试弹窗 private shouldTriggerRetry(error: any): boolean { // 示例规则:网络错误(status=0)、服务器5xx错误、401令牌过期 return error.status === 0 || (error.status >= 500 && error.status < 600) || error.status === 401; } // 创建并显示重试Alert弹窗 private async presentRetryAlert(): Observable<boolean> { const alert = await this.alertCtrl.create({ header: '请求失败', message: '遇到网络异常或服务器问题,是否重试当前请求?', buttons: [ { text: '取消', role: 'cancel', handler: () => {} }, { text: '重试', handler: () => {} } ] }); await alert.present(); // 监听弹窗关闭事件,返回用户的选择结果 const dismissResult = await alert.onDidDismiss(); // 如果用户没点取消,就视为同意重试 return dismissResult.role !== 'cancel'; } }
关键细节说明
- 错误判断逻辑:
shouldTriggerRetry方法可以根据你的业务需求调整,比如只针对特定接口、特定错误码开启重试。 - 弹窗异步处理:因为AlertController的方法是异步的,我们用
async/await处理弹窗的创建和关闭,最后转换成Observable和拦截器的流对接。 - 请求复用:重试时直接复用已经注入令牌的
request对象,无需重新处理令牌逻辑。
扩展:令牌过期的特殊重试场景
如果是401令牌过期的情况,通常需要先刷新令牌再重试,你可以在错误处理里加入这个逻辑:
// 修改catchError中的逻辑 catchError((error) => { if (error.status === 401) { // 先尝试刷新令牌 return this.injector.get(AuthProvider).refreshToken().pipe( switchMap((newToken) => { // 刷新成功后,更新请求头的令牌并重试 const updatedRequest = req.clone({ setHeaders: { Authorization: `Bearer ${newToken}` } }); return next.handle(updatedRequest); }), catchError(() => { // 刷新令牌失败,弹出登录提示 return this.presentLoginRequiredAlert(); }) ); } else if (this.shouldTriggerRetry(error)) { return this.presentRetryAlert().pipe( switchMap((userWantsRetry) => userWantsRetry ? next.handle(request) : of(error)) ); } return of(error); })
最后别忘了在你的AppModule中注册拦截器:
@NgModule({ providers: [ { provide: HTTP_INTERCEPTORS, useClass: RequestInterceptor, multi: true } ] }) export class AppModule {}
内容的提问来源于stack exchange,提问作者Timothy
相关产品推荐
相关产品推荐

