Angular 13中Get请求后使用async管道处理Observable无数据问题
问题原因
你的错误出在async管道的作用对象不对。
组件里你把getAllCompetitions()返回的Observable赋值给了this.competitions,也就是说competitions本身才是需要被async管道订阅的流,而你在模板里写的competitions?.data | async,是在尝试对data这个普通属性(甚至在流没返回值的时候这个属性根本不存在)用async,自然拿不到任何数据。
你对async管道的核心作用认知没错:它会自动完成订阅、取消订阅的逻辑,但要记住async管道只能接收Observable/Promise类型的输入,它会返回流触发后吐出的普通值,你不能对着流输出值里的属性用这个管道。
正确写法
组件类的代码不需要改,保持原样即可:
this.competitions = this.dataService.getAllCompetitions();
模板部分调整async的位置即可,有两种常用实现:
写法1:直接调整管道优先级
用括号保证async先作用在Observable上,拿到返回值之后再访问data属性遍历:
<div class="competitions-table"> <ul *ngFor="let comp of (competitions | async)?.data">{{comp.name}}</ul> </div>
写法2:配合*ngIf as做单次订阅(推荐)
如果后续模板里还要用到这个接口返回的其他字段,或者要避免多次写| async导致重复触发请求,优先用这个写法:
<div class="competitions-table"> <ng-container *ngIf="competitions | async as competitionRes"> <ul *ngFor="let comp of competitionRes.data">{{comp.name}}</ul> <!-- 同作用域下可以直接访问competitionRes的其他属性,不需要重复加async --> </ng-container> </div>
注意点
- Angular的HttpClient返回的是冷Observable,如果你在模板里多处单独写
competitions | async,每一处都会单独发起一次HTTP请求,用*ngIf as的写法只会订阅一次,不会有重复请求问题 - 不要对已经subscribe拿到的普通值使用async管道,会抛出类型错误
- 安全导航运算符
?要加在async解包之后的取值步骤上,不要加在Observable对象本身和管道之间
内容的提问来源于stack exchange,提问作者Damien Garlinge
相关产品推荐
相关产品推荐

