我有一个Angular 2服务,它需要在初始化时执行异步工作,并且在初始化完成之前不应该可用。
@Injectable()
export class Api {
private user;
private storage;
constructor(private http: Http) {
this.storage = LocalStorage;
this.storage.get('user').then(json => {
if (json !== "") {
this.user = JSON.parse(json);
}
});
}
// one of many methods
public getSomethingFromServer() {
// make a http request that depends on this.user
}
}
目前的情况是,此服务已初始化,并立即返回到使用它的任何组件。然后该组件在其getSomethingFromServer()
中调用ngOnInit
,但此时Api.user未初始化,因此发送了错误的请求。
生命周期钩子(OnInit
,OnActivate
等)不能用于服务,只能用于组件和指令,所以我不能使用它们。
从get()
调用存储Promise将需要依赖于用户的所有不同方法等待它,导致大量代码重复。
在Angular 2中对服务进行异步初始化的推荐方法是什么?
答案 0 :(得分:6)
在与Thierry的答案进行了一些讨论之后,我发现它只会工作一次,但它确实让我走上了正确的道路。我不得不存储用户的承诺,并创建一个新的observable,然后flatMap
- 编辑。
@Injectable()
export class Api {
private userPromise: Promise<User>;
constructor(private http: Http) {
this.userPromise = LocalStorage.get('user').then(json => {
if (json !== "") {
return JSON.parse(json);
}
return null;
});
}
public getSomethingFromServer() {
return Observable.fromPromise(this.userPromise).flatMap((user) => {
return this.http.get(...).map(...);
});
}
}
}
这可以确保flatMap
函数在每次调用时都会让用户获得,而不是像Thierry的回答中那样第一次。
答案 1 :(得分:5)
您可以使用flatMap
运算符来使用observable。如果用户不在那里,您可以等待它,然后链接目标请求。
以下是一个示例:
@Injectable()
export class Api {
private user;
private storage;
private userInitialized = new Subject();
constructor(private http: Http) {
this.storage = LocalStorage;
this.storage.get('user').then(json => {
if (json !== "") {
this.user = JSON.parse(json);
this.userInitialized.next(this.user);
}
});
}
// one of many methods
public getSomethingFromServer(): Observable<...> {
// make a http request that depends on this.user
if (this.user) {
return this.http.get(...).map(...);
} else {
return this.userInitialized.flatMap((user) => {
return this.http.get(...).map(...);
});
}
}
}