Sla*_* II 5 rxjs reactivex angular
考虑到我有一个调用服务器并通过Observable返回用户数据的函数:
getUserById (id: number): Observable<User> {
return this.http.get('/users/' + id)
.map(response => response.json())
;
}
Run Code Online (Sandbox Code Playgroud)
我如何使其表现得更像诺言?
问题是,只有有人订阅了返回的可观察对象,才会发出请求。另外,完成多个订阅后,服务器将被多次调用。
我想要的是:
在被调用时立即调用服务器getUserById()(订阅应该是可选的,只有在调用者确实想要获取返回值或在请求完成时才知道的情况下)
多个订阅不应产生多个请求,而应返回从服务器获得的相同值
使用这种方法,我将能够使此功能起作用:
refreshUser (): Observable<User> {
return repository.getUserById(this.currentUser.id)
.map(user => this.currentUser = user)
;
}
Run Code Online (Sandbox Code Playgroud)
调用时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));
Run Code Online (Sandbox Code Playgroud)
我尝试使用publish(),refCount()并且share()以不同的组合使用,但是它仅对第一个要求有所帮助(即避免多次调用服务器),但是如何使原始的可观察性变热呢?
经过使用不同选项的进一步研究之后,似乎使用getUserById()热解决方案无法解决该问题,因为我在不同级别上有两个映射函数(一对一getUserById()和一对in refreshUser()),并且我需要它们都执行。为了解决这个问题,我需要以某种方式从下到上“推动”可观察对象。看起来每个级别都需要大量样板代码。
在诺言中,它看起来非常简单:
getUserById (id: number): Promise<User> {
return this.http.get('/users/' + id)
.map(response => response.json())
.toPromise()
;
}
Run Code Online (Sandbox Code Playgroud)
refreshUser (): Promise<User> {
return repository.getUserById(this.currentUser.id)
.then(user => {
this.currentUser = user;
return user;
})
;
}
Run Code Online (Sandbox Code Playgroud)
使用RxJS是否有更简单的解决方案,或者Promises实际上更适合这项工作?
看起来您需要使用 a 或Subjector aBehaviorSubject而不仅仅是普通的 Oberservable。就您而言, aBehaviorSubject更好,因为它存储当前值。
声明两个变量,一个是普通User类型,另一个是 a BehaviorSubjectof User:
currentUser:User;
userBSubject:BehaviorSubject<User>;
Run Code Online (Sandbox Code Playgroud)
因为您需要 的初始值BehaviorSubject,所以您可以在构造函数中初始化它:
constructor(){
this.userBSubject = new BehaviorSubject<User>(this.currentUser)
}
Run Code Online (Sandbox Code Playgroud)
所以这就是神奇的地方。每次您需要修改(在您的情况下,“刷新”)数据时,您都会调用该方法.next():
refreshUser() {
return repository.getUserById(this.currentUser.id)
.subscribe(user => {
this.userBSubject.next(user);
return this.userBSubject.asObservables()
});
}
Run Code Online (Sandbox Code Playgroud)
然后你可以这样做:
// Just refreshes the current user
refreshUser();
// Refreshes the current user and obtains fresh data
refreshUser().subscribe(user => console.log('Refreshed user', user));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
897 次 |
| 最近记录: |