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

如何在Angular的http请求中通过pipe和map添加catchError处理401错误

问题原因与解决方案

1. 首次类型报错的原因

RxJS的catchError操作符要求回调函数必须返回一个Observable类型的值,你首次实现中直接返回错误对象err,RxJS会自动将其包装为类型为unknown的Observable,和函数声明的返回值Observable<CursorResult[]>类型不匹配,因此触发TS类型报错。

2. 无限调用的原因

catchError回调的第二个参数caught就是当前触发错误的原始请求Observable,你直接return caught等价于告诉RxJS重新订阅这个请求Observable,也就是重新发起接口调用。当接口持续返回401错误时,就会进入「报错→重发请求→再报错」的死循环,就是你看到的无限调用现象。

正确实现代码

单接口临时实现

如果只需要给这个接口加401处理,参考代码如下:

import { catchError, throwError } from 'rxjs';
import { Router } from '@angular/router';

// 先在构造函数注入Router
constructor(private _http: HttpClient, private router: Router) {}

getViT(x): Observable<CursorResult[]> {
  const url = hosturl +'vit';
  const httpOptions = {
    headers: new HttpHeaders({
      'Access-Control-Allow-Origin':  '*',
      'Content-Type': 'application/json',
      'Authorization': ls
    }),
    withCredentials: true,
    params: {}
  };
  return this._http.get<CursorResult[]>(url, httpOptions)
  .pipe(
    map((res) => <CursorResult[]> res),
    catchError((err) => {
      console.log('API Error: ', err);
      // 判断是否为401 token过期
      if (err.status === 401) {
        // 执行登出逻辑:清空本地存储的token、用户信息
        localStorage.removeItem('token');
        localStorage.removeItem('userInfo');
        // 跳转登录页
        this.router.navigate(['/login']);
      }
      // 抛出错误给上层调用方处理,避免类型不匹配
      return throwError(() => err);
    }),
  )     
}

最佳实践:全局拦截器统一处理

推荐使用Angular的HttpInterceptor全局拦截所有HTTP请求,统一处理401错误,不需要每个接口重复写逻辑:

// auth-interceptor.ts
import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor,
  HttpErrorResponse
} from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { Router } from '@angular/router';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(private router: Router) {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    return next.handle(request).pipe(
      catchError((err: HttpErrorResponse) => {
        if (err.status === 401) {
          // 全局登出逻辑
          localStorage.removeItem('token');
          this.router.navigate(['/login']);
        }
        return throwError(() => err);
      })
    );
  }
}

之后在AppModule的providers里注册拦截器即可:

providers: [
  { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 20:36:04