Angular 6:如何为'root'提供HTTP_INTERCEPTORS并使用拦截器服务
Angular 6+ 中配置HTTP拦截器的正确方式
嘿,这个问题我刚好踩过坑,来给你捋清楚怎么处理~
首先得明确:HTTP拦截器没办法直接用provideIn: 'root'来自动注册,因为HTTP_INTERCEPTORS是Angular的多提供者令牌,这类令牌需要显式声明multi: true来支持多个拦截器共存,而@Injectable的provideIn语法目前不支持为多提供者配置自动注册逻辑。
不过你依然可以给拦截器加上@Injectable装饰器(方便注入其他依赖服务),然后通过模块的providers数组来完成注册,具体步骤如下:
1. 编写拦截器服务
给你的拦截器添加上@Injectable装饰器,这样如果需要注入其他服务(比如AuthService获取token)会更方便:
import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable() export class InterceptorService implements HttpInterceptor { // 这里可以注入其他依赖,比如AuthService constructor() {} intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { // 你的拦截逻辑示例:给请求添加Authorization头 const authRequest = request.clone({ setHeaders: { Authorization: `Bearer ${localStorage.getItem('token')}` } }); return next.handle(authRequest); } }
2. 在模块中注册拦截器
你需要在AppModule(或者专门的CoreModule)的providers数组里配置HTTP_INTERCEPTORS令牌,注意必须加上multi: true,否则会覆盖其他拦截器:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; import { InterceptorService } from './interceptor.service'; import { AppComponent } from './app.component'; @NgModule({ declarations: [AppComponent], imports: [BrowserModule, HttpClientModule], // 记得导入HttpClientModule providers: [ { provide: HTTP_INTERCEPTORS, useClass: InterceptorService, multi: true // 关键!允许多个拦截器同时生效 } ], bootstrap: [AppComponent] }) export class AppModule {}
3. 进阶:用CoreModule统一管理核心服务
如果你的项目比较大,建议把拦截器这类核心服务放到CoreModule中,通过forRoot()方法确保只注册一次:
// core.module.ts import { NgModule, ModuleWithProviders } from '@angular/core'; import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { InterceptorService } from './interceptor.service'; @NgModule({}) export class CoreModule { static forRoot(): ModuleWithProviders<CoreModule> { return { ngModule: CoreModule, providers: [ { provide: HTTP_INTERCEPTORS, useClass: InterceptorService, multi: true } ] }; } }
然后在AppModule中导入:
// app.module.ts import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { HttpClientModule } from '@angular/common/http'; import { CoreModule } from './core/core.module'; import { AppComponent } from './app.component'; @NgModule({ declarations: [AppComponent], imports: [BrowserModule, HttpClientModule, CoreModule.forRoot()], bootstrap: [AppComponent] }) export class AppModule {}
关键提醒
- 永远不要省略
multi: true:如果不加这个属性,Angular会用你的拦截器覆盖所有已注册的其他拦截器,导致它们失效。 - 拦截器的执行顺序和你在
providers数组中的注册顺序一致,所以如果有多个拦截器,要注意排列顺序。
内容的提问来源于stack exchange,提问作者Miloš Tomšik
相关产品推荐
相关产品推荐

