我正在使用APP_INITIALIZER,就像this回答一样,我的服务返回一个承诺,但它并不总是等待它解决,我可以看到我的组件console.logging undefined然后服务记录下载的对象。
我需要应用程序在加载此数据之前不执行任何操作。
app.module.ts
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { Http, HttpModule, JsonpModule } from '@angular/http';
import { UserService } from '../services/user.service';
<...>
@NgModule({
imports: [
BrowserModule,
HttpModule,
FormsModule,
JsonpModule,
routing
],
declarations: [
AppComponent,
<...>
],
providers: [
<...>
UserService,
{provide: APP_INITIALIZER,
useFactory: (userServ: UserService) => () => userServ.getUser(),
deps: [UserService, Http],
multi: true
}
],
bootstrap: [AppComponent]
user.service.ts
@Injectable()
export class UserService {
public user: User;
constructor(private http: Http) { }
getUser(): Promise<User> {
console.log('get user called');
var observable= this.http.get('/auth/getuser', { headers: getHeaders() })
.map(extractData);
observable.subscribe(user => {this.user = user;
console.log(this.user)});
return observable.toPromise();
}
}
答案 0 :(得分:17)
请尝试以下代码:
getUser(): Promise<User> {
console.log('get user called');
var promise = this.http.get('/auth/getuser', {headers: getHeaders()})
.map(extractData)
.toPromise();
promise.then(user => {
this.user = user;
console.log(this.user);
});
return promise;
}
我遇到了同样的问题,使用诺言而不是观察对我来说是个窍门。
答案 1 :(得分:2)
我认为问题是由于您订阅了observable而引起的。 这应该工作
@Injectable()
export class UserService {
public user: User;
constructor(private http: Http) { }
getUser(): Promise<User> {
console.log('get user called');
return observable= this.http.get('/auth/getuser', { headers: getHeaders() })
.map(extractData)
.do(user => {
this.user = user;
console.log(this.user)
})
.toPromise();
}
}
我不确定toPromise()
是否必要。我希望它也适用于Observable
。
答案 2 :(得分:1)
使用Promise保护您的路线,使用Promise加载配置设置也应该有效。
将appSettings.service与返回promise
的函数一起使用getAppSettings(): Promise<any> {
var observable = this.http.get(this.ApiUrl, { headers: this.headers })
.map((response: Response) => {
var res = response.json();
return res;
});
observable.subscribe(config => {
this.config= config;
console.log(this.config)
});
return observable.toPromise();
}
CanActivate后卫如下:
import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { AppSettingsService } from './appsettings.service';
@Injectable()
export class CanActivateViaAuthGuard implements CanActivate {
//router: Router
constructor(private appSettingsService: AppSettingsService)
{
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.appSettingsService.getAppSettings().then(() => {
return true });
}
}
这将确保在构造相应组件时您的设置可用。 (使用APP_INITIALIZER并没有限制被调用的构造函数,所以我不得不使用这个技术,另外请确保,你不要导出导出中的所有组件:模块中的[])
为了保护路由并确保在调用构造函数之前加载设置,请使用路径定义路径中常用的canActivate选项
path: 'abc',
component: AbcComponent,
canActivate: [CanActivateViaAuthGuard]
appsettings的初始化应该在调用AbcComponent的构造函数之前发生,这是在Angular 2.0.1中测试并运行的
我不确定它是否是加载配置的正确位置,但似乎是为了达到目的
答案 3 :(得分:0)
迟到了,但如果你想让你的Service类返回Observables(我这样做),请在你的App Module类中这样调用它:
function authenticationFactory(service: AuthenticationService) {
console.log("calling login");
//Call auth service login to get JWT info and startup data.
//Also convert from an Observable to a Promise to work with APP_INITIALIZER.
return () => service.login().toPromise().then(/*do nothing here*/);
}
NgModule Metadata stuff...
providers: [
...
AuthenticationService,
{
provide: APP_INITIALIZER,
useFactory: authenticationFactory,
deps: [AuthenticationService],
multi: true
},
...
],