Angular RxJS中forkJoin返回Observable<boolean>类型错误求助
解决RxJS类型错误:Observable<Observable>无法赋值给Observable
问题场景
你编写的loadUser函数期望返回Observable<boolean>类型,但出现类型错误提示:
Type 'Observable<Observable<boolean>>' is not assignable to type 'Observable<boolean>'
你的代码如下:
public loadUser(): Observable<boolean> { return forkJoin([this.getUser(), this.getUserEntitlements()]).pipe( switchMap(([userId, userEntitlements]) => { const consolidatedResp = { 'userId': userId, 'userEntitlements': userEntitlements } this.userId = consolidatedResp.userId.toLowerCase(); this.processUIEntitlements(userEntitlements); if (consolidatedResp.userEntitlements.firstName) { return of(consolidatedResp); } else { return this.getUserDetails(this.userId) } }), map((userDetails: IUserInfo | { userId: string, userEntitlements: ICurrentUser }) => { if (userDetails) { if (!('userEntitlements' in userDetails)) { this.userInfo = userDetails; this.setUserName(); } return of(true) } else { return of(false) } }) ) }
问题原因
你猜的没错——map操作符里返回了of(true)/of(false),导致流的类型变成了Observable<Observable<boolean>>。map的作用是把流中的每个值转换成另一个值,而不是返回新的Observable;如果要返回Observable,应该用switchMap这类高阶映射操作符,但这里完全没必要包装成Observable,直接返回布尔值即可。
修复方案
把map里的of(true)和of(false)改成直接返回true和false,同时保持map操作符不变:
public loadUser(): Observable<boolean> { return forkJoin([this.getUser(), this.getUserEntitlements()]).pipe( switchMap(([userId, userEntitlements]) => { const consolidatedResp = { 'userId': userId, 'userEntitlements': userEntitlements } this.userId = consolidatedResp.userId.toLowerCase(); this.processUIEntitlements(userEntitlements); if (consolidatedResp.userEntitlements.firstName) { return of(consolidatedResp); } else { return this.getUserDetails(this.userId) } }), map((userDetails: IUserInfo | { userId: string, userEntitlements: ICurrentUser }) => { if (userDetails) { if (!('userEntitlements' in userDetails)) { this.userInfo = userDetails; this.setUserName(); } // 直接返回布尔值,不再用of包装 return true; } else { return false; } }) ) }
额外优化建议
如果你的逻辑中需要在map之后执行一些副作用(比如修改类属性),更规范的做法是把副作用代码放到tap操作符里,让map只负责值的转换,职责更清晰:
public loadUser(): Observable<boolean> { return forkJoin([this.getUser(), this.getUserEntitlements()]).pipe( switchMap(([userId, userEntitlements]) => { const consolidatedResp = { 'userId': userId, 'userEntitlements': userEntitlements } this.userId = consolidatedResp.userId.toLowerCase(); this.processUIEntitlements(userEntitlements); if (consolidatedResp.userEntitlements.firstName) { return of(consolidatedResp); } else { return this.getUserDetails(this.userId) } }), // 用tap处理副作用 tap((userDetails: IUserInfo | { userId: string, userEntitlements: ICurrentUser }) => { if (userDetails && !('userEntitlements' in userDetails)) { this.userInfo = userDetails; this.setUserName(); } }), // map只负责返回布尔值 map((userDetails) => !!userDetails) ) }
内容的提问来源于stack exchange,提问作者Mitul Panchal
相关产品推荐
相关产品推荐

