How to call an asynchronous service before bootstrap ?

Sometimes, we have to fetch datas before our application boostrap is started. It happens when we have to fetch a server configuration before calling an API. Angular offers a poorly documented system : the APP_INITIALIZER provider.

APP_INITIALIZER is a multi provider, that is, a provider that accepts several values. But this provider is special because it accepts promises. As long as all promises aren't resolved, your application will wait. It's a good place for fetching a configuration !

Suppose we have a service that would search for a configuration on a remote server. To simulate the http request, we will use the asynchronous method setTimeOut. Here is our service :

 

 

Now, we would like to call the load method before the application bootstrap. Thus, a component can use this service during the bootstrap ! APP_INITIALIZER will play this role. But, how to configure this provider ? This is not trivial, so here is the configuration : 

 

 

Then, during the initialization stage, Angular will execute the load function. Here is the Angular code that wait to resolve promises :

 

 

This is a plunker that uses this mecanism :

 

 

 

William Koza

William Koza

Consultant Indépendant chez  
Passionné par la conception et le développement logiciel, j’ai rapidement pris le rôle de Technical Leader lors de mes premiers projets. Ces expériences ont ainsi pu me faire accéder à des rôles d’architecte dans des projets d’envergure. Aujourd'hui, j'exerce mon métier en tant qu'indépendant, et toujours avec la même passion.
William Koza

Les derniers articles par William Koza (tout voir)

  • Keleka Kevo

    Hi, I can’t get this solution to work with AOT while building for production. It gives the errors,
    `$$_gendir/app/app.module.ngfactory.ts (208,52): Supplied parameters do not match any signature of call target.
    $$_gendir/app/app.module.ngfactory.ts (208,52): Supplied parameters do not match any signature of call target.`

    Do you have a way around this?

  • William Koza

    I suppose you have this error:
    ERROR in Error encountered resolving symbol values statically. Function calls are not supported. Consider replacing the function or lambda with a reference to an exported function (position 22:19 in the original .ts file), resolving symbol AppModule in ...
    You should export yous factory like this:

    export function configFactory(config: ConfigService) {
    return () => config.load();
    }

    And use it in your module :


    @NgModule({
    declarations: [
    AppComponent
    ],
    imports: [
    BrowserModule,
    FormsModule,
    HttpModule
    ],
    providers: [
    ConfigService,
    {
    provide: APP_INITIALIZER,
    useFactory: configFactory,
    deps: [ConfigService],
    multi: true
    }
    ],
    bootstrap: [AppComponent]
    })
    export class AppModule { }

  • Pingback: [Angular] Init un service avant le chargement | DevBieres()