考虑到我有一个函数,它调用服务器并通过可观察的方式返回用户数据:
getUserById (id: number): Observable<User> {
return this.http.get('/users/' + id)
.map(response => response.json())
;
}
,我如何使它表现得更像一个承诺呢?
问题是,除非有人订阅返回的可观察对象,否则不会发出请求。此外,当完成多个订阅时,服务器将被多次调用。
我想要的是:
getUserById()
时立即调用服务器(订阅应该是可选的,只有当调用方真正希望获得返回的值或关心请求何时完成时,订阅才是可选的)通过这种方法,我将能够使这个函数发挥作用:
refreshUser (): Observable<User> {
return repository.getUserById(this.currentUser.id)
.map(user => this.currentUser = user)
;
}
在调用refreshUser()
时,应该发出请求,并对this.currentUser = user
进行评估。如果需要,我可以订阅返回的可观察到的数据,以便获得新的数据,例如:
// 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()
,但是它只会帮助满足第一个需求(即避免对服务器的多次调用),但是如何使原始的可观察到的热?
更新
经过对不同选项的进一步研究后,似乎使用getUserById()
热的解决方案并不能解决这个问题,因为我有两个不同级别的映射函数(一个在getUserById()
中,一个在refreshUser()
中),我需要执行这两个函数。为了解决这个问题,我需要从下往上推可观察到的东西。看起来每个级别都需要大量的样板代码。
在承诺中,这看起来非常简单:
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解决方案,或者承诺实际上更适合这项工作?
发布于 2017-06-21 22:05:58
从你的描述看,你似乎可以这样做:
getUserById (id: number): Observable<User> {
const observable = this.http.get('/users/' + id)
.map(response => response.json())
.publishReplay(1)
.refCount()
.take(1);
observable.subscribe();
return observable;
}
如果您多次订阅来自getUserById
的相同的可观察返回,则始终会得到相同的结果。
发布于 2017-06-21 18:21:12
看起来,您需要使用一个或Subject
或一个BehaviorSubject
,而不是仅仅使用一个普通的Oberservable。在您的示例中,BehaviorSubject
存储当前值更好。
声明两个变量,一个是普通的User
类型,另一个是BehaviorSubject
of User
currentUser:User;
userBSubject:BehaviorSubject<User>;
因为您需要BehaviorSubject
的初始值,所以可以在构造函数中初始化它:
constructor(){
this.userBSubject = new BehaviorSubject<User>(this.currentUser)
}
所以这就是魔法的来源。每次您需要修改(在您的例子中是“刷新”)数据时,您都会调用方法.next()
refreshUser() {
return repository.getUserById(this.currentUser.id)
.subscribe(user => {
this.userBSubject.next(user);
return this.userBSubject.asObservables()
});
}
然后你就可以:
// Just refreshes the current user
refreshUser();
// Refreshes the current user and obtains fresh data
refreshUser().subscribe(user => console.log('Refreshed user', user));
https://stackoverflow.com/questions/44688706
复制