angular: APP_INITIALIZER with useFactory Compilation Error on first run

I’m submitting a … (check one with “x”)

[x] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior When using APP_INITIALIZER with useFactory I have an error on first compilation run, on the second run the error goes away.

Expected behavior No errors on first compilation run.

Minimal reproduction of the problem with instructions

@NgModule({
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: fooFactory,
      deps: [MainConfigService],
      multi: true
    },
  ],
...

export function foo(mainConfigService) {
  return function() {
    return mainConfigService.loadConf();
  };
};

export function fooFactory(mainConfigService: MainConfigService) {
  return foo(mainConfigService);
}

What is the motivation / use case for changing the behavior? We need a working demo/way to asynchronously bootstap the application.

Please tell us about your environment: The issue has been replicated on Windows 10 and Ubuntu 16.04.1 LTS

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 16 (9 by maintainers)

Most upvoted comments

@mrucelum … or use // @dynamic comment … just put it exactly before the line with @NgModule.

// @dynamic
@NgModule({...})

And then you can use:

export function appConfigServiceFactory(config: AppConfig) {
	return () => config.load().then((status) => {
		...
	});
}

I have got down to the root of my problem, The APP_INITIALIZER was actually a red herring the real issue was with the way I was declaring the ngrx Store

// was 
export const appStore =  compose(storeLogger(), combineReducers)({
    toasts: registerReducer(ToastReducer, toastInitState)
});

// needs to be
const reducers = {
  toasts: registerReducer(ToastReducer, toastInitState)
};

const developmentReducer = compose(storeLogger(), combineReducers)(reducers);

export function reducer(state: any, action: any) {
  return developmentReducer(state, action);
}

Plus after that I had to remove all the default of the modules declared with export default. After that the problem was solved. Unfortunately I had to result to dichotomy to find what was the issue. The Error was completely misleading. Thank you for the support though.

try to change

export function fooFactory() {
  return foo();
}

to

export function fooFactory() {
  return () => foo();
}

@cmckni3 … you can’t use an arrow function in that place. Use exported factory function like:

providers: [
	...,
	AppConfig,
	{
		provide: APP_INITIALIZER,
		useFactory: appConfigServiceFactory,
		deps: [AppConfig],
		multi: true
	},
	...
]

where appConfigServiceFactory is something like:

export function appConfigServiceFactory(config: AppConfig) {
	return () => config.load().then((status) => {
		...
	});
}

I’ve just tested this:

@NgModule({
  imports: [ BrowserModule],
  declarations: [ App ],
  bootstrap: [ App ],
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: fooFactory,
      deps: [],
      multi: true
    }
    ]
})
export class AppModule {}

export function fooFactory() {
  return () => loadConfig({});
}

export function loadConfig(config: any) {
  console.log('do load', config);
}

and it works just fine. 2.0.10 ts 2.4.6 angular

Yes, I had an exported function and switched to arrow function which broke it. Switched back to fix it.