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
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
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
When I'm not coding...
Me and Tina are on a motorcycle adventure around Australia.
Come along for the ride!