How To Handle Async Providers in Angular
Explaining an issue loading the value for a base API URL from a configuration file and using it with an InjectionToken

Update: I wrote a follow-up story to this with a better solutions here: https://medium.com/better-programming/follow-up-how-to-handle-async-providers-in-angular-54957c7349c4
If you’re not sure what that title means, don’t worry. Let me explain.
I recently ran into an issue where we needed to load the value for a base API URL (e.g., http://localhost:9000) from a configuration file and use that value with an InjectionToken
in our app.
I’m going to explain what I ended up doing in this blog post.
APP_INITIALIZER Saves the Day
You’re probably familiar with APP_INITIALIZER
. If not, I recommend reading this article over on Angular InDepth.
APP_INITIALIZER
lets you hook into Angular’s bootstrapping process to do things before the rest of the app has loaded.
The service
Let’s create the service for loading the config.
Pretty simple, right? getBaseUrl()
performs a GET
request on /assets/config.json
and uses some RxJS magic to extract the property baseUrl
from the resulting JSON.
It also stores the resulting value in a private property baseApiUrl
which is exposed with the getter baseUrl
. I added loadConfig()
in case multiple values need to be loaded. loadConfig()
is also what we are going to use for the APP_INITIALZER
.
The AppLoadModule
The AppLoadModule
will provide APP_INITIALIZER
. The code is also pretty straightforward.
We add a factory function which takes our service as the first parameter. In it, we return a function returning a promise — the promise being the thing we want to do.
Thanks to RxJS, we can use the RxJS goodness throughout our app and convert it to a promise when needed. We could also use the HttpClient
directly in the factory function, but the more code you can share within your app, the better.
The next thing we need to do is provide
APP_INITIALIZER
.
useFactory
tells Angular which factory function to use. You could also write that in-line.deps
tells Angular which Services or other injectables are needed to handle the factory. The order in which you put in thedeps
affects how you need to order the parameters of your function.
And that’s it for the AppLoadModule
.
The ConfigModule
The last module we need is the ConfigModule
. Creating a separate module for this isn’t necessary but can clean things up in larger applications, in my opinion.
All we do here is provide an InjectionToken
called BASE_API_URL_TOKEN
. I used this throughout my app to tell services “where” the API server is.
We use a factory because we need access to the ConfigService
. useFactory
and deps
do the same things as above with the difference being that factories for providers do not support promises, which is the entire reason this article is even necessary.
All that’s left to do now, is to import
both Modules in your module of choice and you’re good to go.
Summary
I can’t help but think that there is or should be a better way to do this. I also think the solution I described here isn’t that bad.
If you want to check out my full example, I created a GitHub repository which you can clone, run, and inspect for yourself.
Wrapping up, all we really needed to do was use Angular’s APP_INITIALIZER
to load configurations before the rest of our application is available and save them in a Service. Providing them is pretty easy once we have them inside our application.
If you have any suggestions or even better solutions to this, please leave them down below.
Thanks for reading!