【发布时间】:2017-11-25 02:26:48
【问题描述】:
考虑到我有一个调用服务器并通过 Observable 返回用户数据的函数:
getUserById (id: number): Observable<User> {
return this.http.get('/users/' + id)
.map(response => response.json())
;
}
如何让它表现得更像 Promise?
问题是,在有人订阅返回的 observable 之前不会发出请求。另外,当多个订阅完成时,服务器会被调用多次。
我想要的是:
在调用
getUserById()时立即调用服务器(订阅应该是可选的,仅当调用者确实想获取返回值或想知道请求何时完成时)多个订阅不应产生多个请求,而应返回从服务器获得的相同值
通过这种方法,我将能够使此功能发挥作用:
refreshUser (): Observable<User> {
return repository.getUserById(this.currentUser.id)
.map(user => this.currentUser = user)
;
}
当调用refreshUser() 时,应发出请求并评估this.currentUser = user。如果我愿意,我可以订阅返回的 observable 以获得新的数据,例如:
// Just refreshes the current user
refreshUser();
// Refreshes the current user and obtains fresh data
refreshUser().subscribe(user => console.log('Refreshed user', user));
我尝试以不同的组合使用publish()、refCount() 和share(),但它仅有助于满足第一个要求(即避免多次调用服务器),但我如何使原始的 observable热吗?
更新
在使用不同选项进行进一步调查后,使getUserById() 变热的解决方案似乎无法解决它,因为我在不同级别上有两个映射函数(一个在getUserById() 和一个在refreshUser()),我需要两者其中执行。为了解决这个问题,我需要以某种方式将 observable 从底部“推”到顶部。而且看起来每个级别都需要大量样板代码。
在 promises 中看起来很简单:
getUserById (id: number): Promise<User> {
return this.http.get('/users/' + id)
.map(response => response.json())
.toPromise()
;
}
refreshUser (): Promise<User> {
return repository.getUserById(this.currentUser.id)
.then(user => {
this.currentUser = user;
return user;
})
;
}
有没有更简单的 RxJS 或 Promises 解决方案实际上更适合这项工作?
【问题讨论】:
-
简单但肮脏:在返回 observable 之前,在服务中订阅它。
-
我不明白。如果你只使用
getUserById到refreshUser,那应该总是发出另一个请求。为什么要getUserByIdhot?