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