StaticInjectorError[HttpClent]:适配静态注入器手动注入HttpClientModule问题
解决StaticInjectorError[HttpClient]:从ReflectiveInjector迁移到StaticInjector的正确姿势
你这个问题我太熟了!之前从ReflectiveInjector转StaticInjector的时候也踩过一模一样的坑。核心原因是StaticInjector是Angular的低级静态注入器,它不支持直接注入NgModule(比如HttpClientModule),而旧的ReflectiveInjector可以动态解析NgModule里的providers,所以之前的代码能正常跑,换StaticInjector就直接报错了。
下面给你两种解决方案,优先推荐第一种,简单又靠谱:
方案一:复用应用根注入器(强烈推荐)
既然你的应用已经加载了HttpClientModule,直接拿根注入器来用就好,完全不需要手动构建StaticInjector。
修改你的AppInjector代码
import { Injector, Type, InjectionToken } from '@angular/core'; export class AppInjector { private static _instance: AppInjector; private _injector: Injector; private constructor(injector: Injector) { this._injector = injector; } // 在应用启动时初始化,传入根注入器 static initialize(injector: Injector): void { if (!AppInjector._instance) { AppInjector._instance = new AppInjector(injector); } } // 对外暴露获取实例的方法 static get<T>(token: Type<T> | InjectionToken<T>): T { return AppInjector._instance._injector.get(token); } }
在main.ts中初始化注入器
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; import { AppInjector } from './app/appInjector'; platformBrowserDynamic().bootstrapModule(AppModule) .then(moduleRef => { // 拿到根注入器,初始化我们的AppInjector AppInjector.initialize(moduleRef.injector); }) .catch(err => console.error(err));
之后你在任何地方需要HttpClient,直接调用AppInjector.get(HttpClient)就行,和之前的用法完全一致,但不会再报错了——因为根注入器已经包含了HttpClientModule的所有依赖。
方案二:手动构建StaticInjector(仅适用于完全独立于应用的场景)
如果你真的需要一个完全独立于应用的注入器,那得手动把HttpClient的所有依赖都配齐,因为StaticInjector不会帮你自动解析NgModule的providers。示例代码如下:
import { StaticInjector } from '@angular/core'; import { HttpClient, HttpHandler, HttpRequest, HttpEvent } from '@angular/common/http'; import { XhrBackend, BrowserXhr, NoopXSRFStrategy, XSRFStrategy } from '@angular/common/http'; import { Observable } from 'rxjs'; // 实现HttpHandler,委托给XhrBackend class SimpleHttpHandler implements HttpHandler { constructor(private backend: XhrBackend) {} handle(req: HttpRequest<any>): Observable<HttpEvent<any>> { return this.backend.handle(req); } } // 手动配置所有需要的providers const providers = [ BrowserXhr, XhrBackend, { provide: XSRFStrategy, useClass: NoopXSRFStrategy }, // 不需要XSRF防护的话用这个 { provide: HttpHandler, useFactory: (backend: XhrBackend) => new SimpleHttpHandler(backend), deps: [XhrBackend] }, HttpClient ]; // 创建StaticInjector并获取HttpClient const injector = new StaticInjector(providers); const httpClient = injector.get(HttpClient);
不过这种方式非常繁琐,你得自己维护所有依赖链,所以除非万不得已,不建议用这种方法。
内容的提问来源于stack exchange,提问作者fastAsTortoise
相关产品推荐
相关产品推荐

