Angular拦截器异常求助:无法捕获401错误且不跳转登录页
解决Angular拦截器的两个问题:无法捕获401错误与路由跳转失效
问题1:无法捕获401错误,error.status为0
出现status=0的核心原因及修复方案:
- 跨域(CORS)配置缺失:后端未正确配置CORS规则,当返回401响应时,浏览器因跨域安全策略拦截了真实响应,导致前端拿到的是
status=0的兜底错误。需要后端在响应头中添加Access-Control-Allow-Origin、Access-Control-Allow-Credentials等必要字段,确保401响应能被浏览器正常放行。 - 错误类型判断错误:你代码里的
error instanceof HttpResponse属于无效代码(既没做条件判断,也判断错了类型),拦截器捕获的请求错误应为HttpErrorResponse类型,需先判断类型再读取状态码:import { HttpErrorResponse } from '@angular/common/http'; // ... catchError(error => { if (error instanceof HttpErrorResponse) { // 正确判断错误类型 if (error.status === 401) { // 后续处理逻辑 } } // ... })
问题2:执行登出后未跳转到登录页
修复路由跳转失效的关键要点:
- 明确路由路径:
this.router.navigate([''])可能指向的不是登录页,需改为明确的登录路由,比如this.router.navigate(['/login'])。 - 在NgZone中执行跳转:拦截器的错误处理属于RxJS流,某些情况下路由跳转可能脱离Angular变更检测,需注入
NgZone并在其内部执行跳转:import { NgZone } from '@angular/core'; // ... constructor( private tokenSerice: TokenService, private usuarioService: UsuarioService, private router: Router, private ngZone: NgZone // 注入NgZone ){} // ... this.usuarioService.logout(); this.ngZone.run(() => { this.router.navigate(['/login']); }); - 正确处理错误流:当前代码捕获401后未返回有效Observable,会导致流中断,需补充返回
EMPTY或重新抛出错误,保证逻辑完整执行:import { EMPTY, throwError } from 'rxjs'; // ... if (error.status === 401) { this.usuarioService.logout(); this.ngZone.run(() => { this.router.navigate(['/login']); }); return EMPTY; // 若无需传播错误则用EMPTY,否则用throwError抛出 } else { return throwError(() => error.message); }
完整修正后的拦截器代码
import { Injectable } from '@angular/core'; import { HttpRequest, HttpHandler, HttpInterceptor, HttpErrorResponse } from '@angular/common/http'; import { Observable, EMPTY, throwError } from 'rxjs'; import { catchError } from 'rxjs/operators'; import { TokenService } from './token.service'; // 替换为你的实际路径 import { UsuarioService } from './usuario.service'; // 替换为你的实际路径 import { Router } from '@angular/router'; import { NgZone } from '@angular/core'; @Injectable() export class RequestInterceptor implements HttpInterceptor { constructor( private tokenSerice: TokenService, private usuarioService: UsuarioService, private router: Router, private ngZone: NgZone ) { } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<any> { if (this.tokenSerice.hasToken()) { const token = 'Bearer ' + this.tokenSerice.getToken(); req = req.clone({ setHeaders: { 'Authorization': token, } }); } return next.handle(req).pipe( catchError((error: HttpErrorResponse) => { if (error.status === 401) { this.usuarioService.logout(); this.ngZone.run(() => { this.router.navigate(['/login']); }); return EMPTY; } else { return throwError(() => error.message || '未知错误'); } }) ); } }
内容的提问来源于stack exchange,提问作者rlp master
相关产品推荐
相关产品推荐

