Angular2 загрузка конфигурации из бэкэнд при запуске
В моем приложении Angular2 я пытаюсь загрузить конфигурации из бэкэнд на bootstrap с помощью HTTP, чтобы я мог использовать извлеченные данные для создания angular служб.
Всякий раз, когда я пытаюсь прочитать HTTP-ответ, сохраненный в моем Config, я всегда получаю TypeError: не могу прочитать свойство "url" ошибки undefined.
Похоже, что HTTP-запрос завершается только тогда, когда заканчивается весь метод начальной загрузки, тогда как мой код пытается извлечь ответ Observable до его получения.
Как я могу исправить его для извлечения конфигурации с сервера и использовать его для создания служб angular при запуске? (Я хочу создавать службы внутри провайдеров с извлеченными данными)
Прокомментируйте, если есть лучший способ извлечения конфигурации с сервера при запуске.
Мой main.ts выглядит следующим образом:
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');
}
}
Ответы
Ответ 1
Вы можете использовать службу APP_INITIALIZER
для перезагрузки конфигурации до запуска приложения:
bootstrap(AppComponent, [
{
provide: APP_INITIALIZER,
useFactory: (config:Config) => {
return config.load();
},
dependency: [ Config ]
}
]);
Для этого вам нужно немного адаптировать ваш класс ConfigService
:
@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();
});
}
}
Затем вы сможете напрямую получить доступ к объектам конфигурации в своем приложении.
Ответ 2
При использовании компиляции AoT он выдает ошибку, поскольку factory является анонимной функцией. Что вам нужно сделать, это экспортировать функцию для factory
export function ConfigLoader(configService: ConfigService) {
return () => configService.load();
}
и конфигурация для приложения выглядит так:
@NgModule({
declarations: [
AppComponent
],
imports: [
HttpModule,
BrowserModule
],
providers: [
ConfigService,
{
provide: APP_INITIALIZER,
useFactory: ConfigLoader,
deps: [ConfigService]
}],
bootstrap: [ AppComponent ]
})
export class AppModule {
}
ссылка https://github.com/angular/angular/issues/10789
Ответ 3
Это лучший способ написать функцию загрузки
public load() {
let promise =this.http.get(url).map(res => res.json()).toPromise();
promise.then(config => this.validation = config);
return promise;
};