Angular中如何实现仅首次需要时通过Observable请求Token并复用
重构方案
核心问题根源
你之前的实现有两个核心问题:
- 同步的token getter无法等待异步的HTTP请求完成,自然拿不到刚请求到的token
- 你在
subscribe回调中返回的Observable不会被外层函数接收到,token不存在的分支下函数没有合法返回值,调用方会直接报错
最终重构代码
import { catchError, shareReplay, switchMap, throwError } from 'rxjs'; import { HttpHeaders, HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { environment } from '你的environment配置文件路径'; export class Service { private readonly api_url: string = environment.API_URL; // 缓存token的Observable,避免重复请求 private token$?: Observable<string>; constructor(private http: HttpClient) {} getToken(): Observable<string> { // 仅当没有缓存时才发起请求 if (!this.token$) { this.token$ = this.http.get<string>(`${this.api_url}/你的服务端token接口路径`).pipe( // 缓存1次结果,后续订阅直接复用缓存 shareReplay(1), // 请求出错时清空缓存,方便下次调用重试 catchError(err => { delete this.token$; return throwError(() => err); }) ); } return this.token$; } // 封装通用的带认证头的请求方法,所有第三方接口调用都走这个方法 private requestWithToken<T>(method: string, partnerUrl: string, options?: any): Observable<T> { return this.getToken().pipe( // 拿到token后再发起实际的第三方请求 switchMap(token => { const headers = new HttpHeaders({ 'Authorization': `Bearer ${token}` }); const finalOptions = { ...options, headers }; return this.http.request<T>(method, partnerUrl, finalOptions); }) ); } partnerFirstFunction(): Observable<any> { return this.requestWithToken('POST', 'partnerUrl'); } partnerSecFunction(): Observable<any> { return this.requestWithToken('PATCH', 'partnerUrl'); } // 新增第三方接口只需要一行代码,无需重复写token判断逻辑 partnerThirdFunction(): Observable<any> { return this.requestWithToken('GET', '另一个partnerUrl'); } }
实现效果说明
- 按需请求:只有第一次调用需要token的接口时才会发起token获取请求,后续所有接口调用直接复用缓存的token,不会重复发请求
- 异步等待:如果同一时间发起多个需要token的接口请求,所有请求都会等待第一次token请求完成后再执行,不会出现缺少认证头的问题
- 无重复代码:token获取、认证头拼接逻辑全部封装在公共方法中,后续新增接口只需一行调用代码,维护成本极低
可选扩展
如果你的token有有效期,可以在requestWithToken方法中增加token过期判断,过期时清空this.token$即可触发重新获取新token。
内容的提问来源于stack exchange,提问作者Patrick Freitas
相关产品推荐
相关产品推荐

