Angular TypeScript订阅Observable返回对象控制台有值但代码属性为undefined
问题核心原因
1. 控制台的延迟求值特性
浏览器控制台打印引用类型(数组、对象)时,保存的是对象的引用,只会在你手动点击展开内容时才会读取对象的当前值。你看到打印结果有数据,不代表执行console.log那一行代码时对象就已经有值,很可能是代码执行完成后,数组才被异步填充了数据,你后续展开控制台才看到了最新值。
2. TypeScript 类型断言无运行时效果
你在订阅回调里标注的depotDays: DepotDayAcc[]只是编译期的类型提示,不会做任何运行时的类型转换。后端返回的是普通JSON对象,并没有通过new DepotDayAcc()实例化,所以不会带上类定义里的默认属性,类型不匹配自然会出现属性为undefined的情况。
解决方案
第一步:验证执行时刻的真实数据
先将打印代码替换为深拷贝后的快照,避免控制台延迟求值的干扰,确认代码执行时的真实数据状态:
// 序列化再反序列化拿到当前时刻的静态快照 console.log(JSON.parse(JSON.stringify(depotDays)))
如果打印结果为空数组,或者第一个元素不存在对应属性,对应下面的方案处理。
第二步:处理空数组提前推送的问题
如果你的getData()接口会先推送空数组、后续才推送有值的数组,可以加过滤逻辑跳过空值场景:
import { filter } from 'rxjs'; this.backendService.getData() .pipe(filter(data => Array.isArray(data) && data.length > 0)) .subscribe(depotDays => { // 这里的逻辑只会在拿到非空数组时执行 })
第三步:手动做类实例映射
不要直接把后端返回的普通对象当做DepotDayAcc实例使用,需要手动遍历映射为类实例:
this.backendService.getData().subscribe((rawList: any[]) => { const depotDays = rawList.map(raw => new DepotDayAcc( new Date(raw.day), raw.investment, raw.profit, raw.value, raw.percent, new Set(raw.tickers || []) )); // 现在depotDays里的元素都是正规的DepotDayAcc实例,可以正常访问所有属性 })
内容的提问来源于stack exchange,提问作者Plagueis
相关产品推荐
相关产品推荐

