0

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], }, 
9
  • You need to resolve the dependency before the app will be initialized. I guess that APP_INITIALIZER helps. Commented Sep 30, 2016 at 0:42
  • Thanks @estus, is there an example where this is used? Commented Sep 30, 2016 at 1:42
  • It isn't covered by the reference yet. You may use search, there's a plenty of answered question on SO that cover APP_INITIALIZER, e.g. stackoverflow.com/a/38128065/3731501 . Commented Sep 30, 2016 at 4:03
  • Looks interesting its worrying that it is undocumented and marked as "experimental". Regardless I tried to use it and got: Unhandled Promise rejection: appInits[i] is not a function ; Zone: <root> ; Task: Promise.then ; Value: TypeError: appInits[i] is not a function. Commented Oct 2, 2016 at 21:17
  • 1
    APP_INITIALIZER should be a function that returns a promise. I.e. useFactory: (configService: ConfigService) => () => configService.load(). Here's how it works (it isn't documented but quite straightforward). Commented Oct 2, 2016 at 21:34

1 Answer 1

2

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). Since APP_INITIALIZER is multi-provider, there can be many initializers, they will be executed in parallel and awaited. 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 an initializer without dependencies:

{ provide: APP_INITIALIZER, useValue: () => promise, multi: true } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.