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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 08:17:21