Published: December 09 2022

Angular - Execute an init function before app startup with an Angular APP_INITIALIZER

Tutorial built with Angular 14.2.12

This is quick post on how to use APP_INITIALIZER to execute an asynchronous initialization function before an Angular app starts up.

Init functions are useful for any tasks you want to run before your app starts, such as loading configuration data or fetching user profile information.

The example code is from an Angular JWT + Refresh Token tutorial I posted recently, it attempts to automatically authenticate the user on app startup by sending an HTTP request to the API for a new auth token. For the full tutorial including a live demo see Angular 14 - JWT Authentication with Refresh Tokens Example & Tutorial.

 

App Initializer

Path: /src/app/_helpers/app.initializer.ts

The app initializer attempts to automatically login to the Angular app on startup by calling authenticationService.refreshToken() which sends a request to the API for a new JWT auth token. If the user previously logged in (without logging out) the browser will have a valid refresh token cookie that is sent with the request to generate a new JWT. On success the app starts on the home page with the user already logged in, otherwise the login page is displayed.

Returned Observable must complete

When an Angular app initializer function returns an Observable like this one, the observable must complete before the app can startup. An observable is complete when it has finished emitting all values without any errors. The catchError() operator is used to ensure the observable always reaches the completed state even if the refreshToken() request fails.

Can also return Promise or void

It's also possible to return a Promise from an initializer function, in which case the Promise must resolve before the app can startup. For synchronous init tasks you can simply omit the return statement which sets the return type to void.

Configured as provider in app module

The appInitializer is configured as an Angular initialization function in the providers section of the app module. It's added with the injection token APP_INITIALIZER and has dependencies (deps) set to [AuthenticationService]. For more info see https://angular.io/api/core/APP_INITIALIZER.

import { AuthenticationService } from '@app/_services';
import { catchError, finalize, of } from 'rxjs';

export function appInitializer(authenticationService: AuthenticationService) {
    return () => authenticationService.refreshToken()
        .pipe(
            // catch error to start app on success or failure
            catchError(() => of())
        );
}
 

Angular App Module

Path: /src/app/app.module.ts

The app module defines the root module of the application along with metadata about the module. The imports specify which other angular modules are required by this module, the declarations state which components belong to this module, and the providers configure dependency injection for the module including HTTP_INTERCEPTORS and the APP_INITIALIZER.

The above appInitializer function is configured on line 30, the multi: true property indicates that the injection token (APP_INITIALIZER) is a multi-provider token meaning you can add multiple initializer functions if required.

For more info on Angular modules see https://angular.io/docs/ts/latest/guide/ngmodule.html.

import { NgModule, APP_INITIALIZER } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';

// used to create fake backend
import { fakeBackendProvider } from './_helpers';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';

import { JwtInterceptor, ErrorInterceptor, appInitializer } from './_helpers';
import { AuthenticationService } from './_services';
import { HomeComponent } from './home';
import { LoginComponent } from './login';

@NgModule({
    imports: [
        BrowserModule,
        ReactiveFormsModule,
        HttpClientModule,
        AppRoutingModule
    ],
    declarations: [
        AppComponent,
        HomeComponent,
        LoginComponent
    ],
    providers: [
        { provide: APP_INITIALIZER, useFactory: appInitializer, multi: true, deps: [AuthenticationService] },
        { provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true },
        { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },

        // provider used to create fake backend
        fakeBackendProvider
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

 


Need Some Angular Help?

Search fiverr for freelance Angular developers.


Follow me for updates

On Twitter or RSS.


When I'm not coding...

Me and Tina are on a motorcycle adventure around Australia.
Come along for the ride!


Comments


Supported by