I need to get the config using a factory that will be resolved during the APP INITIALIZATION (using the APP_INITIALIZER provider).
export function loadConfig(): () => Promise<Config> {
// return promised config
}
That is provided using the AppModule:
providers: [{
provide: APP_INITIALIZER,
useFactory: loadConfig,
deps: [HttpClient, ConfigService],
multi: true
}]
Then I need to use that configuration data in inject something inside another InjectionToken, but if I provide the specific injectiontoken using the config provided during the app initialization, that process is executed before the APP_INITIALIZER execution.
export const FORMATS = new InjectionToken<Formats>("formats")
export assignFormat(configService: ConfigService) {
return configService.getFormats(); // Needs to execute after APP_INITIALIZER, not before
}
providers: [{
provide: APP_INITIALIZER,
useFactory: loadConfig,
deps: [HttpClient, ConfigService],
multi: true
}, {
provide: FORMATS,
useFactory: assignFormat,
deps: [ConfigService]
}]
@Injectable({ providedIn: "root" })
export class ConfigService {
constructor() {}
getFormats() {}
}
How can I do to provide the injection token after the APP initialization?
CodePudding user response:
What you have here should actually work, if your loadConfig
factory returns a function instead of the actual promise:
const loadConfig = (configService: ConfigService) => {
return () =>
new Promise<void>((resolve, reject) => {
// I added the timeout to simulate a delay
setTimeout(() => {
// you might be using a http call to get the config from the server instead.
// Make sure you keep the config that you fetched in the service;
// this way you can inject the service in the next factory function
// and have the config available
configService.config = {
formats: 'formats',
};
resolve();
}, 1000);
});
};
The provision of the APP_INITIALIZER
looks exactly like in your code:
{
provide: APP_INITIALIZER,
useFactory: loadConfig,
deps: [ConfigService],
multi: true,
},
When you set up the next injection token, you should have the config available to use
{
provide: FORMATS,
useFactory: (configService: ConfigService) => {
// getFormats method must not be async, it needs to return the actual
// formats that were fetched during the app initialization phase
return configService.getFormats();
},
deps: [ConfigService],
},
The only async factories that are allowed in Angular are the ones you use with the APP_INITIALIZER
injection token, but beware that from these, you need to return a function instead of the actual value.