How to call an rest api while bootstrapping angular 2 app How to call an rest api while bootstrapping angular 2 app angular angular

How to call an rest api while bootstrapping angular 2 app


You can use APP_INITIALIZER to call a service method at bootstrap. You will require to define a provider for it in your AppModule.

Here is an example of how to do this.

StartupService (startup.service.ts)

import { Injectable } from '@angular/core';import { Http, Response } from '@angular/http';import 'rxjs/add/operator/map';import 'rxjs/add/operator/toPromise';@Injectable()export class StartupService {    private _startupData: any;    constructor(private http: Http) { }    // This is the method you want to call at bootstrap    // Important: It should return a Promise    load(): Promise<any> {        this._startupData = null;        return this.http            .get('REST_API_URL')            .map((res: Response) => res.json())            .toPromise()            .then((data: any) => this._startupData = data)            .catch((err: any) => Promise.resolve());    }    get startupData(): any {        return this._startupData;    }}

AppModule (app.module.ts)

import { BrowserModule } from '@angular/platform-browser';import { NgModule, APP_INITIALIZER } from '@angular/core';import { StartupService } from './startup.service';// ...// Other imports that you may require// ...export function startupServiceFactory(startupService: StartupService): Function {    return () => startupService.load();}@NgModule({    declarations: [        AppComponent,        // ...        // Other components & directives    ],    imports: [        BrowserModule,        // ..        // Other modules    ],    providers: [        StartupService,        {            // Provider for APP_INITIALIZER            provide: APP_INITIALIZER,            useFactory: startupServiceFactory,            deps: [StartupService],            multi: true        }    ],    bootstrap: [AppComponent]})export class AppModule { }

EDIT (How to handle startup service failure):

AppComponent (app.component.ts)

import { Component, OnInit } from '@angular/core';import { Router } from '@angular/router';import { StartupService } from './startup.service';@Component({    selector: 'app-root',    templateUrl: './app.component.html',    styleUrls: ['./app.component.scss']})export class AppComponent implements OnInit {    constructor(private router: Router, private startup: StartupService ) { }    ngOnInit() {        // If there is no startup data received (maybe an error!)        // navigate to error route        if (!this.startup.startupData) {            this.router.navigate(['error'], { replaceUrl: true });        }    }}


One thing I came across using the answer provided by Santanu is that it wont work unless StartupService is defined in the providers before the APP_INITIALIZER. Using Angular 4.x, so the providers part looks like this in my case:

  providers: [    UserService,  {    provide: APP_INITIALIZER,    useFactory: userServiceFactory,    deps: [UserService],    multi: true  }


@efirvida & @Santanu Biswas

I tried your answer and it works (content in APP_INITIALIZER happens before app.component bootstrapping).

Unfortunately, the injections in all components happen before it, so that components refer to variables not ready yet.

I opened a question here.

It is basically the same question that @magos asked.

Any help well accepted ^^

The only solution I can think of is to make API calls in app.component to get config data, but is not properly what is needed for both OP and me.Will be my solution if I can't solve the syncronism issue