如何从NgRx Select订阅中返回实际值而非Observable类型的结果
问题解决方案
你遇到的类型错误本质是 subscribe() 方法的返回值是Subscription订阅对象,不是你在回调函数里返回的布尔值。RxJS是基于异步流的设计,没有办法让一个同步函数直接返回流里推送的异步值,必须调整写法适配响应式编程的逻辑。
方案1(最推荐):返回Observable,上层适配响应式逻辑
这是NgRx+RxJS开发的标准写法,不需要手动订阅管理生命周期,配合Angular的async管道还能自动取消订阅避免内存泄漏。
修改函数代码如下:
private checkMemberIsNotPremium(memberId): Observable<boolean> { return this.store .pipe( select(getSelectedMemberType(), {id: memberId}), // 用map操作符直接转换流里的值 map((val: any) => val.membershipType !== 'Premium') ); }
上层调用如果是在模板里渲染,直接绑定用async管道即可:
<div *ngIf="checkMemberIsNotPremium(memberId) | async">非 premium 会员可见内容</div>
如果是在业务逻辑里用,订阅后处理即可:
this.checkMemberIsNotPremium(memberId).subscribe(isNotPremium => { // 在这里执行需要布尔值的逻辑 if (isNotPremium) { // 对应操作 } })
方案2:用async/await转换成Promise调用
如果你确实需要用同步写法拿值,可以用RxJS 7+提供的firstValueFrom工具方法把Observable转换成Promise,配合async/await使用:
import { firstValueFrom, take, map } from 'rxjs'; private async checkMemberIsNotPremium(memberId): Promise<boolean> { return firstValueFrom( this.store .pipe( select(getSelectedMemberType(), {id: memberId}), map((val: any) => val.membershipType !== 'Premium'), take(1) // 取第一个值就结束流,避免无限等待 ) ); }
上层调用时用await接收值:
// 注意外层函数需要标记为async const isNotPremium = await this.checkMemberIsNotPremium(memberId); // 接下来处理业务逻辑
方案3(不推荐):同步订阅取值
如果必须要函数直接返回布尔值,可以用闭包变量存结果,但要注意必须加take(1)自动取消订阅,否则会有内存泄漏风险,而且如果store还没初始化对应值,可能拿到错误的默认值:
private checkMemberIsNotPremium(memberId): boolean { let isNotPremium = false; this.store .pipe( select(getSelectedMemberType(), {id: memberId}), take(1) ) .subscribe((val: any) => { isNotPremium = val.membershipType !== 'Premium'; }); return isNotPremium; }
这种写法只适合你确定store已经提前加载完对应member数据的场景,否则逻辑会出问题,非常不推荐。
内容的提问来源于stack exchange,提问作者Bwizard
相关产品推荐
相关产品推荐

