user509755
user509755

Reputation: 2981

How to call an rest api while bootstrapping angular 2 app

We would like to call a rest api when angular 2 app being bootstrapped, i mean first thing it should do about the application is call this api and get some data which is required for application.

Is there anyway to achieve this? I saw following article but it was meant for beta version of Angular 2

Sample Code based on Angular 2 beta or rc

Reading data before app start up

Upvotes: 53

Views: 27651

Answers (4)

Dusan Mancic
Dusan Mancic

Reputation: 141

One thing I came across using the answer provided by Santanu is that it won't work unless StartupService is defined in the providers before the APP_INITIALIZER. I'm 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
  }
]

Upvotes: 13

Eaden
Eaden

Reputation: 43

@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

Upvotes: 0

NR Ganesh
NR Ganesh

Reputation: 111

Here is an article which explains APP_INITIALIZER in much more detail and it also shows how angular uses it.

Upvotes: -2

Santanu Biswas
Santanu Biswas

Reputation: 4787

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 });
        }
    }

}

Upvotes: 113

Related Questions