我正在构建一个Angular 4服务,该服务提供对某些数据的访问。当这项服务是第一次 实例化后,它需要建立与数据存储的连接,这是一个异步过程。
如何在此异步连接过程完成之前,最好地阻止此服务的用户(即,组件或其他服务)尝试使用该服务?
我的服务是否有某种方式可以告诉Angular的引导程序在继续之前等待此承诺解决?
如果重要,该服务已在我providers
的{{1}}数组中注册。所以(据我所知),Angular将构建一个服务实例,该实例将提供给注入@NgModule
的任何组件或其他服务。
明确地说,这是我害怕的情景:
在应用程序引导过程中,Angular会在模块的MyService
数组中看到MyService
,并调用其构造函数。
providers
的构造函数开始连接过程,可能需要一两秒钟。
与此同时,Angular的引导程序继续向前充电,并呈现我的应用程序的仪表板。
仪表板组件注入MyService
,并且(在其自己的构造函数中,或者可能在MyService
中)尝试在建立连接之前调用ngOnInit
。
为了说明这里的服务:
myService.getData()
答案 0 :(得分:1)
您需要做的是延迟应用初始化,直到建立连接。您可以使用下面的APP_INITIALIZER
令牌来执行此操作,
onAppInit Factory返回初始化承诺
export function onAppInit(svc: MyService): () => Promise<any> {
return svc.initialize;
}
AppModule
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
providers: [
MyService,
{
provide: APP_INITIALIZER,
useFactory: onAppInit,
deps: [MyService],
multi: true
}
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
<强>为MyService 强>
@Injectable()
export class MyService{
connection;
constructor(){}
initialize = (): Promise<any> => {
return new Promise( (resolve, reject) => {
setTimeout(() => {
this.connection = {
data : {
"var1": "xyz"
}
};
resolve();
}, 3000);
});
}
getData = () => {
console.log(this.connection);
return this.connection.data;
}
}
AppComponent
@Component({
selector: 'my-app',
template: `<h1>Hello</h1>
<hr />
{{data | json}}
`
})
export class AppComponent {
data;
constructor(private svc: MyService){ }
ngOnInit(){
this.data = this.svc.getData();
}
}
这可以解决您在问题中的问题,但请注意,在初始化服务之前,您的应用程序不会呈现,这可能是糟糕的用户体验,具体取决于可接受的延迟数 强>
更好的解决方案是从@JBNizet评论中建议的getData()返回promise或Observable。
希望这会有所帮助!!