How to handle async providers in Angular
An elegant solution to a common problem.

Passionate about developing solutions that make an impact.
Search for a command to run...
An elegant solution to a common problem.

Passionate about developing solutions that make an impact.
No comments yet. Be the first to comment.
Loading a configuration at the start of an Angular app is a common task. Traditionally, you would utilize APP_INITIALIZER to accomplish this (Angular InDepth has a great piece on this). This works great most of the time.
There are, however, a few situations where this is suboptimal. For example when you are using an internal Component Library that has too much logic (🙄) and already has APP_INITIALIZERS hooks setup. This can cause issues where the execution order of all the hooks is not how you need it to be.
There is actually a really easy solution to this - and I don't think a lot of people know about it.
You probably know that every Angular project has a file called main.ts that usually looks something like this:
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch(err => console.error(err));
Notice the call to platformBrowserDynamic? If you check the official docs for this you can see that this function actually takes an array of providers as a parameter. Perfect!
With that in mind, the solution looks like this:
main.ts file using the native fetch APINow, your main.ts could look like this:
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { BASE_API_URL_TOKEN } from './app/injectors';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
async function main() {
try {
const data = await fetch('/assets/config.json');
const config = await data.json();
await platformBrowserDynamic([
{ provide: BASE_API_URL_TOKEN, useValue: config.baseUrl },
]).bootstrapModule(AppModule);
} catch (error) {
console.error(error);
}
}
main();
And that's it. You can checkout the example repo on GitHub
Always read the docs!
Cheers!