【问题标题】:StaticInjectorError[HttpClent]: Function/class not supportedStaticInjectorError [HttpClient]:不支持函数/类
【发布时间】:2018-10-11 14:57:19
【问题描述】:

我正在尝试手动注入HttpClientModule,该HttpClientModule 从应用程序独立运行outside(可能是!)。在静态注入器之前,我使用反射注入器并且代码工作正常,但现在反射注入器已被弃用,我想用静态注入器更新我的代码。

//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);

请参考This Post 用于注释 fn。 现在,当我尝试将 Http 客户端与静态注入一起使用时,它会给出错误: StaticInjectorError[HttpClent]: Function/class not supported

//app module
@NgModule({
  imports: [],
  declarations: [],
  providers: [],
  entryComponents: [App]
})
export class AppModule {
  ngDoBootstrap(app) {
    console.log('bootstrapping');
    app.bootstrap(App);
  }

所以如果我登录,它将记录app-injector,然后是bootstrapping

【问题讨论】:

    标签: javascript angular typescript angular-httpclient


    【解决方案1】:

    StaticInjector 应该是不需要Reflect API 的ReflectiveInjector 的替代品。 getAnnotations 是低级 hack,在当前状态下它可能无法与 StaticInjector 一起使用。此外,getAnnotations 在设计上与 AOT 不兼容。

    最好按照框架应该完成的方式为模块创建注入器,即应该引导模块。由于没有可引导的组件,因此应指定 ngDoBootstrap 挂钩。

    默认情况下,引导过程是异步的。如果这不是问题,可以链接初始化承诺以获取模块实例。

    example:

    @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 不需要异步初始化。

    example:

    @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 编译器进行编译,并且应该创建一个使用模块工厂的单独入口点。 Bootstrap 例程变得更加简单,因为它不涉及编译器,例如:

    ...
    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();
    

    【讨论】:

    • 谢谢你的详细回答,但如果我按照你所说的去做,我的 AppModule 会去哪里以及我正在做的方式,我可以访问我提供的所有资源应用程序中任何位置的反射注入器数组,并且 AppInjector 甚至在应用程序引导之前就被触发。
    • 我更新了问题。如果您需要更多详细信息,请检查并告诉我,而且我正在运行旧版本的 webpack 而不是 angular cli。尝试一次升级应用程序。
    • 它可以去任何你喜欢的地方,你只需要确保你在需要访问 HttpClient 时已经引导它。在上面列出的代码中,注入器是实例属性_injector,如果需要,您也可以使用它。此代码假定没有 Angular 应用程序,只有与非 Angular 应用程序一起使用的 HttpClient。如果不是这样,这可能是 XY 问题 - 您可以以相同的方式从 Angular 应用程序共享 HttpClient 和注入器。
    猜你喜欢
    • 2019-08-02
    • 1970-01-01
    • 2021-10-25
    • 2011-03-06
    • 1970-01-01
    • 2019-08-23
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多