首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >使其在RxJS中表现得像承诺一样?

使其在RxJS中表现得像承诺一样?
EN

Stack Overflow用户
提问于 2017-06-22 01:34:20
回答 2查看 1.6K关注 0票数 7

考虑到我有一个函数,它调用服务器并通过可观察的方式返回用户数据:

代码语言:javascript
代码运行次数:0
运行
复制
getUserById (id: number): Observable<User> {
  return this.http.get('/users/' + id)
    .map(response => response.json())
  ;
}

,我如何使它表现得更像一个承诺呢?

问题是,除非有人订阅返回的可观察对象,否则不会发出请求。此外,当完成多个订阅时,服务器将被多次调用。

我想要的是:

  • 在调用getUserById()时立即调用服务器(订阅应该是可选的,只有当调用方真正希望获得返回的值或关心请求何时完成时,订阅才是可选的)
  • 多个订阅不应产生多个请求,而应返回从服务器获得的相同值。

通过这种方法,我将能够使这个函数发挥作用:

代码语言:javascript
代码运行次数:0
运行
复制
refreshUser (): Observable<User> {
  return repository.getUserById(this.currentUser.id)
    .map(user => this.currentUser = user)
  ;
}

在调用refreshUser()时,应该发出请求,并对this.currentUser = user进行评估。如果需要,我可以订阅返回的可观察到的数据,以便获得新的数据,例如:

代码语言:javascript
代码运行次数:0
运行
复制
// 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()中),我需要执行这两个函数。为了解决这个问题,我需要从下往上推可观察到的东西。看起来每个级别都需要大量的样板代码。

在承诺中,这看起来非常简单:

代码语言:javascript
代码运行次数:0
运行
复制
getUserById (id: number): Promise<User> {
  return this.http.get('/users/' + id)
    .map(response => response.json())
    .toPromise()
  ;
}
代码语言:javascript
代码运行次数:0
运行
复制
refreshUser (): Promise<User> {
  return repository.getUserById(this.currentUser.id)
    .then(user => {
      this.currentUser = user;
      return user;
    })
  ;
}

是否有更简单的RxJS解决方案,或者承诺实际上更适合这项工作?

EN

回答 2

Stack Overflow用户

发布于 2017-06-22 06:05:58

从你的描述看,你似乎可以这样做:

代码语言:javascript
代码运行次数:0
运行
复制
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的相同的可观察返回,则始终会得到相同的结果。

票数 4
EN

Stack Overflow用户

发布于 2017-06-22 02:21:12

看起来,您需要使用一个或Subject或一个BehaviorSubject,而不是仅仅使用一个普通的Oberservable。在您的示例中,BehaviorSubject存储当前值更好。

声明两个变量,一个是普通的User类型,另一个是BehaviorSubject of User

代码语言:javascript
代码运行次数:0
运行
复制
currentUser:User;
userBSubject:BehaviorSubject<User>;

因为您需要BehaviorSubject的初始值,所以可以在构造函数中初始化它:

代码语言:javascript
代码运行次数:0
运行
复制
constructor(){
  this.userBSubject = new BehaviorSubject<User>(this.currentUser)
}

所以这就是魔法的来源。每次您需要修改(在您的例子中是“刷新”)数据时,您都会调用方法.next()

代码语言:javascript
代码运行次数:0
运行
复制
refreshUser() {
    return repository.getUserById(this.currentUser.id)
      .subscribe(user => {
        this.userBSubject.next(user);
        return this.userBSubject.asObservables()
      });
}

然后你就可以:

代码语言:javascript
代码运行次数:0
运行
复制
// Just refreshes the current user
refreshUser();

// Refreshes the current user and obtains fresh data
refreshUser().subscribe(user => console.log('Refreshed user', user));
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44688706

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档