NgRx 8存储对象属性调用始终返回undefined,求技术解决方案
作为NgRx新手遇到这种问题确实挺挠头的——明明控制台能看到对象带着Name属性,可直接访问却返回undefined,咱们一步步拆解问题、找到解法:
最核心的原因:属性大小写不匹配
你定义的AzureImage类属性是大写开头的(Id, Name, Url),但从Store中取出的实际对象,其属性名大概率是小写开头的(比如后端接口返回的是id, name, url)。
TypeScript的类型标注只是编译时的语法检查,运行时并不会强制对象的属性名和类定义完全一致。当你用k.Name访问时,实际对象里根本没有这个大写的属性,自然返回undefined,而控制台显示的是对象真实的属性(比如小写的name)。
快速验证方法
在subscribe里打印对象的所有键,确认真实属性名:
console.log(Object.keys(k)); // 看输出是["id", "name", "url"]还是["Id", "Name", "Url"]
针对性解决方案
根据验证结果,你可以选以下任一方式修复:
1. 统一属性大小写(推荐)
调整AzureImage类的属性名,和后端返回的格式保持一致:
export default class AzureImage { id: number; name: string; url: string; }
之后所有属性访问都改成小写:k.name。
2. 在数据映射时转换大小写
如果不想修改类的定义,可以在从Store获取数据时手动映射属性:
this.store.pipe(select('azureImages')) .pipe( map(store => { const rawImage = store.AzureImages[id]; // 把后端返回的小写属性映射到类的大写属性 return { Id: rawImage.id, Name: rawImage.name, Url: rawImage.url } as AzureImage; }) ).subscribe((k: AzureImage) => { // 现在访问k.Name就正常了 console.log(k.Name); });
3. 检查数组索引是否正确(额外坑点)
你当前用store.AzureImages[id]获取对象,默认把id当成了数组下标,但如果AzureImage的Id是数据库的唯一标识(不是数组索引),这种方式会拿到错误的对象!
正确的做法是用find方法根据Id匹配:
map(store => store.AzureImages.find(img => img.Id === id))
(如果属性是小写就改成img.id === id)
额外需要修正的细节
你调用aspNetApiService.analyzeImageByAzure后没有订阅这个Observable!RxJS的Observable只有订阅后才会执行逻辑,所以这段代码目前不会生效,需要加上.subscribe():
this.aspNetApiService.analyzeImageByAzure(k.Name) .pipe( map(x => { console.log(x); this.analyzedImage = x; }) ) .subscribe(); // 必须添加订阅才会触发接口请求
内容的提问来源于stack exchange,提问作者Manuel Wolf

