APP_INITIALIZER – Tapping into Initialization Process in Angular

| By Maina Wycliffe | | | Angular

In this post, we are going to look at how we can use APP_INITIALIZER in Angular. So, what exactly does APP_INITIALIZER do? The best way to answer that is by looking at my previous post, which can be found here. It was about angular environment variables being loaded remotely, instead of environment files which are built into the app. So, in this scenario, you might need to have access to those variables immediately the app starts. That’s what APP_INITIALIZER allows you to do, provide a function that will be executed during app initialization stage.

Angular will allow the functions to be executed to completion before rendering anything. It even gets better, if it encounters an error, the whole application will not load. This ensure that your remotely loaded configuration are available right from the start. You can use this to load anything you want to during the initialization stage, so it’s available right after the app starts. To show you how to tap into the initialization process, we are going to use a demo. In this demo, we will look at loading our configurations from the previous post to our angular application. So, without further ado, let’s get started:

Create a New Application

First, Let’s create a brand-new application using Angular CLI.

$ ng new angular-app-initializer-demo-app

And then generate a service to load our configurations:

$  ng generate service config

Next, let’s work on our newly created service to fetch and load our configurations.

Fetching Configurations

One thing to keep in mind before we can go any further, APP_INITIALIZER expects a promise not an observable. Don’t worry, we will still be able to use observables, but our return value must be a promise, otherwise it won’t work. Fortunately for us, RXJS provides a toPromise method to convert that observable to promise. So, our service is going to need one method for getting configurations:

getConfigs(): Promise<Object> { }

And one property for holding our configurations.

configurations: object = null;

Since we don’t have a backend, we will use RXJS of method to convert a simple array into an observable stream. You can easily fetch data using HTTP Client in Angular, just you normally would under any other service. Next, we are going to pipe to our observable and tap into the observable stream to set the configurations property to the returned value. Then convert the observable stream to a promise and return it.

getConfigs(): Promise<Object> {
  return of(dummyConfigs) // <== this could be a http request here
    .pipe(
      tap(config => {
        this.configurations = config;
      })
    )
    .toPromise();
}

Configuring APP_INITIALIZER

We are going to provide APP_INITIALIZER inside App Module, but this can be done in any other module like CoreModule. Before we can do that, we need to create a function to the method for getting our configuration. The function will accept our config service above, which we shall inject when providing APP_INITIALIZER. It will then call the method to get config and return the resulting promise.

export function loadConfigurations(configService: ConfigServiceService) {
  return () => configService.getConfigs();
}

Next, let’s add our config service and provide APPINITIALIZER to our list of providers in the App Module. For the APP_INITIALIZER, first we have the provide property, where we indicated we are providing APPINITIALIZER. Then we indicate we are using factory (_useFactory property) and injecting our config service as a dependency for our factory (_deps property). We have also added a multi property, which indicates we can have multiple APP_INITIALIZERS and not just the one.

@NgModule({
  declarations: [
    //...
    ],
  imports: [
    //...
    ],
  providers: [
    ConfigServiceService,
    {
      provide: APP_INITIALIZER,
      useFactory: loadConfigurations
      deps: [ConfigServiceService], // dependancy
      multi: true
    }
  ],
  bootstrap: [ // ...
]
})

And basically, that’s it. If the promise is resolved successfully, your app should go ahead and load successfully, otherwise it will fail to initialize.

Word of Caution

You can do more complicated stuff but remember that your app won’t start until all sent promises are resolved. So, if you are doing to many things at once, you might impact the performance of your app negatively.

Source Code

You can find the complete source code for this post here.

A Better Approach to Environment Variables in Angular

Angular provides a default way to configure environment variables, which you can learn more about here. But in a nutshell, you have …

Read More
Using App Shell to Improve Performance – Angular 6

Angular apps take time to show meaningful content to the user. This time is mainly after loading the index.html page and bootstrapping the …

Read More
Angular Hidden Treasures – Features you might know About

In this post, we are going to look at four important features in angular that can help you during your app development life cycle. These …

Read More
Angular 6 - Angular CLI Workspaces

One of the least talked about features of Angular 6 is Angular CLI Workspaces. Workspaces or Angular CLI Workspaces give angular developers …

Read More
How to upgrade your Angular 4 App to Angular 5.0

Angular 5 was finally released earlier this week after several delays. It brings a lot of improvements over Angular 4 and new features as …

Read More
Angular 5 has been released

Angular 5 was finally released after several delays yesterday, November 1, 2017. It was also accompanied by Angular CLI 1.5. This is a major …

Read More

Comments