动态创建的模块和组件无权访问父注入器

时间:2019-07-31 19:22:16

标签: angular dependency-injection microservices micro-frontend

我们当前遇到一个问题,我们想动态创建模块(moduleFactory.create(this.injector))。但是动态创建的模块的注入器没有父注入器的提供者。我们希望在集成/主应用程序(在其中创建子模块)中实现一些核心内容,将其放入根注入器中,并希望通过DI(通过与主程序一起创建的注入器)将其添加到子模块和组件中。应用的注入器作为父级。

我们基于以下示例的实现:https://stackblitz.com/edit/angular-ifs7sp?file=src%2Fapp%2Flazy-loader.service.ts

const subsystems = await this.fetchSubsystems()

const promises = subsystems
  .map(async (subsystem) => await subsystem.load())

const subsystemModuleFactories = await Promise.all(promisses)

subsystemModuleFactories.map(async (ngModuleOrNgModuleFactory) => {
  let moduleFactory: NgModuleFactory<any>
  if (ngModuleOrNgModuleFactory instanceof NgModuleFactory) {
    moduleFactory = ngModuleOrNgModuleFactory
  } else {
    const compiler = this.injector.get(Compiler)
    moduleFactory = await compiler.compileModuleAsync(ngModuleOrNgModuleFactory)
  }

  const entryComponent = (<any>moduleFactory.moduleType).entry
  const moduleRef = moduleFactory.create(this.injector) // create the module ref with the injector of the main app as parent of the subsystem module
  // Here we can still get the instance console.log(moduleRef.injector.get(I18n))
  const compFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(entryComponent)

  container.createComponent(compFactory)
})

fetchSubsystems简而言之是使用SystemJS导入单个分发包文件并返回导出的AppModule:

SystemJS.import('subsystem') // mapped to an actual URL
    .then((m) => (m as any).AppModule)

在子系统中,我们要使用该服务:

export class AppComponent {
  public constructor (@Inject(I18n) private i18n: II18n) {
  }
}

I18nInjectionToken,而II18n定义了服务的接口:

import { InjectionToken } from '@angular/core'

export interface II18n {
  tr(key: string): string
}

export const I18n = new InjectionToken<II18n>('I18n')

不幸的是,我们收到一个错误消息,表明注射器中没有这样的InjectionToken:

ERROR Error: Uncaught (in promise): NullInjectorError: StaticInjectorError(AppModule)[AppComponent -> InjectionToken I18n]: 
  StaticInjectorError(Platform: core)[AppComponent -> InjectionToken I18n]: 
    NullInjectorError: No provider for InjectionToken I18n!
NullInjectorError: StaticInjectorError(AppModule)[AppComponent -> InjectionToken I18n]: 
  StaticInjectorError(Platform: core)[AppComponent -> InjectionToken I18n]: 
    NullInjectorError: No provider for InjectionToken I18n!
    at NullInjector.get (core.js:778)
    at resolveToken (core.js:2564)
    at tryResolveToken (core.js:2490)
    at StaticInjector.get (core.js:2353)
    at resolveToken (core.js:2564)
    at tryResolveToken (core.js:2490)
    at StaticInjector.get (core.js:2353)
    at resolveNgModuleDep (core.js:26403)
    at NgModuleRef_.get (core.js:27491)
    at resolveNgModuleDep (core.js:26403)
    at resolvePromise (zone-evergreen.js:797)
    ...

有些意思符合我们的意图(以防万一,这是一个更好的解决方案,但我们尚未找到):我们想要一个类似“微型前端”的东西。我们想要一个集成或主应用程序,它提供了核心应用程序和应用程序的基本布局。我们有多个“子系统”,这些小应用程序为特定的业务逻辑提供GUI(是的,这是一种经典的微服务架构)。因此,据此,在构建子系统时就已经构建了GUI。子系统将GUI作为一个捆绑包提供,集成应用程序应将其加载并安装到应用程序中。

0 个答案:

没有答案