javascript - StaticInjectorError[HttpClent]:不支持的函数/类
我正在尝试手动注入 HttpClientModule,它可能独立于应用程序运行(也许!)。在使用静态注入器之前,我使用的是反射注入器,代码运行良好,但现在反射注入器已经被弃用,我想用静态注入器来更新我的代码。
//appInjector.ts
export class AppInjector {
private static _instance: AppInjector = new AppInjector();
private _injector;
constructor() {
console.log('app-injector');
AppInjector._instance = this;
this._injector = ReflectiveInjector.resolveAndCreate([
...[getAnnotations(HttpClientModule)[0].providers],
MY_HTTP_DEPENDENT_PROVIDERS
]);
static getInstance(): AppInjector {
return AppInjector._instance;
}
get(cls: any): any {
return this._injector.get(cls);
}
}
//someFile.ts
const translate = AppInjector.getInstance().get(TranslateResource);参考此帖子了解注解函数。现在,当我尝试使用带静态注入的 Http 客户端时,它出现错误:StaticInjectorError[HttpClent]: 不支持的函数/类
//app module
@NgModule({
imports: [],
declarations: [],
providers: [],
entryComponents: [App]
})
export class AppModule {
ngDoBootstrap(app) {
console.log('bootstrapping');
app.bootstrap(App);
}所以如果我记录,它将记录 app-injector 然后 bootstrapping。
答案#1
StaticInjector 应该是 ReflectiveInjector 的替代,不需要 Reflect API。getAnnotations 是低级的技巧,可能在当前状态下无法与 StaticInjector 一起使用。此外,getAnnotations 天生与 AOT 不兼容。
最好按照框架规定的方式为模块创建注入器,即模块应该被引导。由于没有组件可以引导,因此应指定 ngDoBootstrap 钩子。
默认情况下,引导过程是异步的。如果这不是问题,可以将初始化的 Promise 链接起来以获取模块实例。
一个例子:
@NgModule({
imports: [BrowserModule, HttpClientModule]
})
export class MyHttpModule {
static httpClient?: HttpClient;
httpClient?: HttpClient;
constructor(private _injector: Injector) {}
ngDoBootstrap() {
MyHttpModule.httpClient = this.httpClient = this._injector.get(HttpClient);
}
}
platformBrowserDynamic().bootstrapModule(MyHttpModule)
.then((myHttpModule: NgModuleRef<MyHttpModule>) => {
// HttpClient instance is available here
const httpClient = myHttpModule.instance.httpClient;
httpClient.get('/foo', { responseType: 'text'}).subscribe();
})
.catch(err => console.error(err));
这种方法开箱即用地兼容 JIT 和 AOT(这对于在 Angular 之外使用 HttpClient 很有好处,因为这会显著降低占用空间)。
否则可以执行自定义同步引导例程。这是可能的,因为HttpClient不需要异步初始化。
一个例子:
@NgModule({
imports: [BrowserModule, HttpClientModule]
})
export class MyHttpModule {
static httpClient?: HttpClient;
constructor(public _injector: Injector) {
MyHttpModule.httpClient = this._injector.get(HttpClient);
}
ngDoBootstrap() {}
}
const platform = platformBrowserDynamic();
const compiler = platform.injector.get(CompilerFactory).createCompiler();
const moduleFactory = compiler.compileModuleSync(MyHttpModule);
platform.bootstrapModuleFactory(moduleFactory)
.catch(err => console.error(err));
const httpClient = MyHttpModule.httpClient;
httpClient.get('/foo').subscribe();
这将在 JIT 中工作,但在上面的代码中,Angular CLI 无法高效处理 AOT。该代码涉及编译器,而在 AOT 编译模式下不需要编译器(这正是它的目的)。为了使用 AOT,应该使用 ngc 编译器进行编译,并创建一个使用模块工厂的单独入口点。引导过程变得更简单,因为它不涉及编译器,比如这样:
...
import { platformBrowser } from '@angular/platform-browser-dynamic';
import { AppModuleNgFactory } from '<path to aot>/src/app/my-http-module.ngfactory';
const platform = platformBrowser();
platform.bootstrapModuleFactory(AppModuleNgFactory)
.catch(err => console.error(err));
const httpClient = MyHttpModule.httpClient;
httpClient.get('/foo').subscribe();
