3

我需要将配置(对象数组)发送到功能模块中的服务,并且需要动态计算此配置。我用过forRoot,它工作得很好,直到我用--aot.

问题:使用--aot,配置结果为undefined

这是我在 stackblitz 上制作的示例的链接: https ://stackblitz.com/edit/angular-aot-forroot-error

!!它可以在 stackblitz 上按需要工作,因为它不是用 aot 构建的!但是,如果您使用 aot 在本地构建它,GetConfigService则会引发错误,因为config它是未定义的。

重要部分:

应用模块:

export const config = [
  {
    id: 'first'
  },
  {
    id: 'second'
  }
];

// just illustrative modification (in my project I need to modify config based on environment)
export function modifyConfig(config) {
  return config.map(c => c.id === 'first' ? {...c, default: true} : c);
}

const configModified = modifyConfig(config);

@NgModule({
  imports:      [
    BrowserModule,
    WithParametersdModule.forRoot(configModified)
  ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

WithParametersdModule:

@NgModule()
export class WithParametersdModule {
  static forRoot(config) {
    return {
      ngModule: WithParametersdModule,
      providers: [
        {
          provide: SOME_CONFIG,
          useValue: config
        },
        GetConfigService
      ]
    }
  }
}

获取配置服务:

@Injectable()
export class GetConfigService {

  constructor(@Inject(SOME_CONFIG) private config) {}

  get configObj() {
    if (!this.config) {
      throw `config: ${this.config}`;
    }

    return this.config;
  }
}

感谢您的帮助或解释我做错了什么。

4

1 回答 1

4

我发现这可能是因为 AOT 会useValue在编译时尝试替换,但是当您在运行时传递这些值时,AOT 只需将其替换为undefined. 解决方案是使用useFactory而不是useValue. 这解决了这个问题。

这是我所做的:

// Declare a function type which returns the config
export type ConfigFunction = () => any;

// Replace useValue with useFactory
@NgModule()
export class WithParametersdModule {
  static forRoot(config: {
    func: ConfigFunction,
    // You could add other config parameters here...
  }) {
    return {
      ngModule: WithParametersdModule,
      providers: [
        {
          provide: SOME_CONFIG,
          useFactory: config.func
        },
        GetConfigService
      ]
    }
  }
}

然后你可以按如下方式使用它:

export function getConfig(): any {
  return {
    id: 'first'
  },
  {
    id: 'second'
  };
}

@NgModule({
  // ...
  imports: [
    BrowserModule,
    WithParametersdModule.forRoot({ func: getConfig }),
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
于 2018-10-28T00:29:37.730 回答