Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
608 views
in Technique[技术] by (71.8m points)

angular - Angular2 load configuration from backend on startup

In my Angular2 app, I'm trying to load configurations from backend on bootstrap using HTTP so that I can use the extracted data for creating angular services.

Whenever I try to read the HTTP response saved in my Config, I always get TypeError: Cannot read property 'url' of undefined error.

It appears like the HTTP request completes only when the whole bootstrap method finishes, whereas my code tries to extract the Observable response before it is retrieved.

How can I fix it to extract configuration from server and use it to create angular services on startup? (I want to create services inside providers with extracted data)

Please comment if there is any better way of extracting configuration from server on startup.

My main.ts looks like this:

bootstrap(AppComponent, 
    [APP_ROUTER_PROVIDERS, HTTP_PROVIDERS, ConfigurationService, Config])
    .catch(err => console.error(err)
);

configuration.service.ts

@Injectable()
export class ConfigurationService {

    constructor(private http: Http) {
    }

    load() {
        return this.http.get('config/getConfig').map(response => response.json());
    }

}

config.ts

@Injectable()
export class Config {

    public config;

    constructor(public configurationService: ConfigurationService) {
        configurationService.load().subscribe(
            config => this.config = config,
            error => console.error('Error: ' + error)
        );
    }

    get(key: any) {
        return this.config[key];
    }
}

app.component.ts

@Component({
    selector: 'app',
    templateUrl: 'app/app.component.html',
    styleUrls: ['app/app.component.css'],
    directives: [ROUTER_DIRECTIVES],
    providers: [MyService]
})
export class AppComponent {

    constructor(public myService: MyService) {
    }

}

my.service.ts

@Injectable()
export class MyService{

    private url;

    constructor(public config: Config) {
        this.url = config.get('url');
    }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You could leverage the APP_INITIALIZER service to reload the configuration before application starts:

bootstrap(AppComponent, [
  {
     provide: APP_INITIALIZER,
     useFactory: (config:Config) => {
       return config.load();
     },
     dependency: [ Config ]
   }
]);

For this, you need to adapt a bit your ConfigService class:

@Injectable()
export class ConfigService {
  constructor(private http:Http) {}

  load() { // <------
    return new Promise((resolve) => {
      this.http.get(...).map(res=>res.json())
        .subscribe(config => {
          this.config = config;
          resolve();
        });
  }
}

Then you'll be able to access directly properties on the configuration object within your application.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...