【问题标题】:Return Observable<boolean> from service method after two subscriptions resolve两个订阅解决后,从服务方法返回 Observable<boolean>
【发布时间】:2018-04-02 15:13:58
【问题描述】:

我正在尝试设置一种简单的方法来将当前用户名与 Angular 服务中的配置文件用户名进行比较。

显然,必须先解析配置文件用户名和用户用户名,然后才能比较它们,那么如何返回布尔可观察对象,以便在组件中订阅此比较?

这就是我所在的地方:

public profileId = new Subject<string>; // Observable string source updated from a profile.component (when the URL displays the profile's username)
public profileId$ = this.profileId.asObservable();
public currentUser = this.principal.asObservable().distinctUntilChanged();

public isProfileOwner(): Observable<boolean> { // A function whose declared type is neither 'void' nor 'any' must return a value.
    this.currentUser.subscribe(user => {
            this.profileId$.subscribe(
                profile => {
                    console.log(profile + ' ' + user.username); // match!
                    if (profile === user.username) {
                        return Observable.of(true);
                    } else {
                        return Observable.of(false);
                    }
                }
            )
        })
}

这似乎是其他 SO 答案的解释方式,但我收到了 [ts] A function whose declared type is neither 'void' nor 'any' must return a value.

我想订阅组件内的测试。

this.authService.isProfileOwner().subscribe(
    data => {
        console.log(data); // should be boolean
    }
)

【问题讨论】:

    标签: angular typescript rxjs rxjs5


    【解决方案1】:

    这可以通过Subject来实现

    import { Subject } from 'rxjs';
    
    public isProfileOwner(): Observable<boolean> {
            var subject = new Subject<boolean>();
    
            this.currentUser.subscribe(user => {
                    this.profileId$.subscribe(
                        profile => {
                            console.log(profile + ' ' + user.username); // match!
                            if (profile === user.username) {
                                subject.next(true);
                            } else {
                                subject.next(false);
    
                            }
                        }
                    )
                })
                return subject.asObservable();
        }
    

    【讨论】:

      【解决方案2】:

      从@user184994 的其他回答中注意到,forkJoin 在这种情况下不起作用。相反,您可以使用combineLatest,然后与@user184994 非常相似地实现了服务代码:

      isProfileOwner(): Observable<boolean> {
        return Observable.combineLatest(this.currentUser, this.profileId$)
          .map(results => {
             let user = results[0];
             let profile = results[1];
             return (user.username === profile)
          });
      }
      

      DEMO

      【讨论】:

      • 这太棒了,我已经更新了问题!我注意到它对我不起作用,因为我最初的 profileIdSubject 源。我需要将其作为主题(我认为),以便 profile.component 可以使用实际的配置文件用户名对其进行更新。然后变成一个流:profileId$ = this.profileId.asObservable();
      • Subject 和 BehaviorSubject 之间的区别基本上是 Subject 需要 next 才能订阅触发。不知道您的完整用例,但我不明白为什么您不能将其作为初始值为 null 的 BehaviorSubject 或其他东西,然后进行 null 检查?你有这种可能吗?
      • 感谢您的耐心等待,我更新了 BehaviorSubject 错误。一个复杂问题的绝佳答案。
      • 没问题,很高兴能帮上忙! user184994 也做得很好,只是需要进行一些小的调整才能使其正常工作,很高兴我们为您提供了解决方案! :)
      【解决方案3】:

      我个人建议使用 forkJoin,等待 observables,然后 flatMap 转换为 Observable&lt;boolean&gt;

      return Observable.forkJoin(this.currentUser, this.profileId$).flatMap(
          results => {
              user = results[0];
              profile = results[1];
              return Observable.of(profile === user.username)
          }
      );
      

      【讨论】:

      • 很好的答案。可以解释我应该如何订阅这个布尔值吗? (得到空白结果)
      • “空白结果”是什么意思?
      • 我已更新问题以显示我的订阅代码。记录结果什么也没显示。
      • 同理,日志信息永远不会被打印出来?
      • 不错。但我认为你可以使用 map() iso flatmap() 吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-25
      • 2018-03-09
      • 2018-11-23
      • 2019-10-26
      • 1970-01-01
      • 2017-02-17
      • 2019-03-09
      相关资源
      最近更新 更多