Angular aot build:动态forRoot参数导致未定义

时间:2018-05-02 09:18:17

标签: angular ng-modules

我需要将配置(对象数组)发送到功能模块中的服务,并且需要动态计算此配置。我使用了forRoot,它工作正常,直到我使用--aot构建它。

问题--aot,配置结果为undefined

这是我在stackblitz上做的一个例子的链接: https://stackblitz.com/edit/angular-aot-forroot-error

!!它在stackblitz上按预期工作,因为它不是用aot构建的!如果你用aot在本地构建它,GetConfigService将抛出一个错误,因为config将是未定义的。

重要部分:

的AppModule:

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
      ]
    }
  }
}

GetConfigService:

@Injectable()
export class GetConfigService {

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

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

    return this.config;
  }
}

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

1 个答案:

答案 0 :(得分:1)

我发现这可能是因为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 { }