Yodacheese Yodacheese - 2 months ago 14
TypeScript Question

Is it possible to set an OpaqueToken via an observable?

I'm trying to set an opaquetoken in the providers using an observable. Reason being is I'm reading the value via the Http provider (external JSON file).

This is what I'm trying to do

{
provide: SOME_OPAQUE_TOKEN,
useFactory: (configService: ConfigService) => {
configService.getPath('campaigns')
.subscribe((res) => {
???
});
},
deps: [ConfigService],
},


So obviously this wont work but I'm wondering if there is a solution for this sort of problem?

Or if its actually possible to construct a service using useFactory where one of your parameters is retrieved asynchronously.

Is it possible at all?

Edit: Solution using APP_INITIALIZER

In AppModule:

{
provide: APP_INITIALIZER,
useFactory: (configService: ConfigService) => () => configService.load(),
multi: true,
deps: [ConfigService, Http],
},


In ConfigService load():

public load(): Promise<Configuration> {
let promise =
this.http
.get('config.json')
.map(m => m.json())
.toPromise();

promise
.then(config => this.appConfig = config);

return promise;
}


Once we set the appConfig we can use it to set the OpaqueToken:

{
provide: BASE_PATH,
useFactory: (configService: ConfigService) => configService.appConfig.basePath, deps: [ConfigService],
},

Answer

APP_INITIALIZER undocumented multi-provider is supposed to be used to resolve app dependencies asynchronously.

An initializer is supposed to be a function that returns a promise (for async initialization) or any other value (for sync initialization). The implementation is here.

It can be defined as a provider in module:

{
  provide: APP_INITIALIZER,
  useFactory: (...deps...) => () => promise,
  deps: [...deps...],
  multi: true
}

Or for a initializer without dependencies:

{
  provide: APP_INITIALIZER,
  useValue: () => promise,
  multi: true
}