Angular13如何根据HTTP请求发起位置为HTTP_INTERCEPTORS添加条件
实现方案
方案一:给初始化请求添加自定义Header(推荐)
通过在初始化阶段发起的HTTP请求中添加专属Header,拦截器据此识别并执行特定逻辑,不会影响其他请求。
1. 在Ngrx Effect中为初始化请求添加Header
处理MyAction.getData的Effect里,调用HTTP请求时注入自定义Header:
import { Injectable } from '@angular/core'; import { Actions, createEffect, ofType } from '@ngrx/effects'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { map, switchMap, catchError } from 'rxjs/operators'; import { of } from 'rxjs'; import * as MyAction from './actions'; @Injectable() export class MyEffects { loadData$ = createEffect(() => this.actions$.pipe( ofType(MyAction.getData), switchMap(() => this.http.get('/api/data', { // 添加初始化请求专属Header headers: new HttpHeaders().set('X-App-Init-Request', 'true') }).pipe( map(data => MyAction.getDataSuccess({ data })), catchError(err => of(MyAction.getDataFailure({ err }))) ) ) ) ); constructor(private actions$: Actions, private http: HttpClient) {} }
2. 在拦截器中识别并处理
在MyHttpInterceptor里检查请求是否携带该Header,执行特定逻辑后可删除Header避免传递给后端:
import { Injectable } from '@angular/core'; import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http'; import { Observable, tap } from 'rxjs'; @Injectable() export class MyHttpInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { // 判断是否为初始化请求 if (req.headers.has('X-App-Init-Request')) { // 执行初始化请求的特定逻辑(比如加载指示器、权限校验等) console.log('处理初始化阶段请求'); // 克隆请求并删除自定义Header,避免传到后端 const modifiedReq = req.clone({ headers: req.headers.delete('X-App-Init-Request') }); return next.handle(modifiedReq).pipe( tap(event => { // 初始化请求完成后的额外处理 }) ); } // 非初始化请求直接放行 return next.handle(req); } }
方案二:通过状态服务标记初始化阶段
创建一个全局服务记录应用是否处于初始化状态,拦截器根据该状态判断请求类型。
1. 实现初始化状态服务
import { Injectable } from '@angular/core'; import { BehaviorSubject, Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class AppInitStateService { private _isInitializing = new BehaviorSubject<boolean>(false); isInitializing$: Observable<boolean> = this._isInitializing.asObservable(); setInitializing(state: boolean): void { this._isInitializing.next(state); } }
2. 在APP_INITIALIZER中更新状态
在app.module.ts的初始化函数中,标记初始化开始与结束:
import { NgModule, APP_INITIALIZER } from '@angular/core'; import { Store } from '@ngrx/store'; import { AppInitStateService } from './app-init-state.service'; import * as MyAction from './actions'; import { selectDataLoaded } from './selectors'; export function appInitializer(store: Store, initStateService: AppInitStateService): () => Observable<any> { return () => { // 标记进入初始化阶段 initStateService.setInitializing(true); return store.dispatch(MyAction.getData()) .pipe( // 等待数据加载完成的状态 concatLatestFrom(() => store.select(selectDataLoaded)), take(1), // 标记初始化结束 tap(() => initStateService.setInitializing(false)) ); }; } @NgModule({ providers: [ { provide: APP_INITIALIZER, useFactory: appInitializer, deps: [Store, AppInitStateService], multi: true } ] }) export class AppModule {}
3. 在拦截器中根据状态处理请求
import { Injectable } from '@angular/core'; import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http'; import { Observable, switchMap, take } from 'rxjs'; import { AppInitStateService } from './app-init-state.service'; @Injectable() export class MyHttpInterceptor implements HttpInterceptor { constructor(private initStateService: AppInitStateService) {} intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return this.initStateService.isInitializing$.pipe( take(1), switchMap(isInitializing => { if (isInitializing) { // 执行初始化请求的特定逻辑 return next.handle(req).pipe( tap(event => { // 额外处理逻辑 }) ); } return next.handle(req); }) ); } }
注意:方案二需注意异步时序问题,如果初始化请求未完成时组件发起其他请求,可能会误判。方案一通过请求级别的Header标记,更精准可靠。
内容的提问来源于stack exchange,提问作者Gnik
相关产品推荐
相关产品推荐

