RxJs BehaviourSubject未向forkJoin.pipe返回当前值问题排查
问题原因
核心原因:forkJoin使用场景错误
forkJoin 运算符的触发规则是:只有所有传入的 Observable 都**完全结束(触发 complete 回调)**时,才会合并所有 Observable 的最后一次发射值,执行后续的 pipe 逻辑。
你传入 forkJoin 的两个 Observable isAuthenticated()、access_token 都派生自 userSubject 生成的热 Observable,BehaviorSubject 除非手动调用 complete() 方法,否则会一直处于可发射值的活跃状态,永远不会触发 complete 回调。因此 forkJoin 会一直处于等待状态,永远不会执行后续的 map 逻辑。
其他可能原因
- 你没有订阅
isInRole()方法返回的 Observable:RxJS 中 Observable 是冷执行模式,只有被主动订阅时才会执行内部的管道逻辑,仅调用方法不做订阅不会触发任何执行。 - 代码语法错误:你粘贴的代码中
isAuthenticated()方法末尾缺失了闭合的},如果实际代码也存在该问题,会导致逻辑执行异常。
修复方案
将 forkJoin 替换为 combineLatest 即可,combineLatest 的规则是:只要所有传入的 Observable 都至少发射过一次值,之后任意 Observable 发射新值时都会合并所有 Observable 的最新值触发后续逻辑,完全适配你需要同时取鉴权状态和令牌最新值的场景。
修改后 isInRole 核心代码如下:
// 先引入combineLatest import { combineLatest } from 'rxjs'; isInRole(roleName: string): Observable<boolean> { console.log(`AuthService.isInRole ${roleName}`); // 把forkJoin换成combineLatest return combineLatest({ isAuthenticated: this.isAuthenticated(), access_token: this.access_token }) .pipe(map(fj => { console.log(`AuthService.isInRole.pipe ${roleName}`); // 原有逻辑不变 if (!fj.isAuthenticated || !fj.access_token) { return false; } const claims: object = jwt_decode(fj.access_token); if ('role' in claims && claims['role'].indexOf(roleName) !== -1) { console.log(`AuthService.isInRole ${roleName} YES`); return true; } if ('http://schemas.microsoft.com/ws/2008/06/identity/claims/role' in claims && claims['http://schemas.microsoft.com/ws/2008/06/identity/claims/role'].indexOf(roleName) !== -1 ) { console.warn('Role claim type is ...microsoft...!'); return true; } return false; })); }
如果还有问题,确保调用 isInRole 时主动订阅了返回值,示例:
authService.isInRole('admin').subscribe(isInRole => { console.log('是否属于管理员角色:', isInRole); })
内容的提问来源于stack exchange,提问作者Richard Barraclough
相关产品推荐
相关产品推荐

