Angular NG0900错误:*ngFor无法遍历对象的技术问询
Angular NG0900错误解决指南
问题概述
在Angular项目中触发ERROR NG0900: 尝试对比'[object Object]'失败,*ngFor仅支持数组和可迭代对象错误。控制台能正常打印目标对象,但无法通过*ngFor遍历渲染视图;使用keyvalue管道只能遍历整个对象的键值对,无法匹配Artifact模型结构,仅需提取API响应中的特定属性值。已查阅RxJS map及Angular keyvalue文档,怀疑TypeScript类型处理存在问题,附上相关代码及API响应,寻求解决方案。
现有代码
组件代码
export class ArtifactCardComponent implements OnInit { allArtifacts: Artifact[] = []; // 声明为数组类型,但API返回单个对象 isFetching: boolean = false; errorMessage: string = ''; // 原代码遗漏该属性 constructor(private artifactService: ArtifactService) {} ngOnInit() { this.artifactService.getArtifacts().pipe( map((data) => { return data['data'] ; // 若API返回单个对象,data['data']可能不存在 } )) .subscribe( (data) => { this.isFetching = true; // 加载状态赋值顺序错误 this.allArtifacts = data console.log(artifacts); // 引用未定义变量,应为this.allArtifacts this.isFetching = false; }, (error) => { this.errorMessage = error.message; } ); } }
模型代码
export class Artifact { id?: string; // API返回数字类型,此处类型不匹配 title: string; date_start: number; date_end: number; artist_display: string; main_reference_number: number; // API返回字符串,类型不匹配 place_of_origin: string; medium_display: string; inscriptions: string; dimensions: number; // API返回字符串,类型不匹配 credit_line: string; department_title: string; }
服务代码
public getArtifacts() { // return this.http.get<Artifact[]>(this.baseURL) : Observable<Artifact[] return this.http.get(this.baseURL, { responseType: 'json' }) // 未指定返回类型 }
视图代码
<div> <ul class="list-group list-group-flush d-flex align-items-start" *ngFor="let artifact of allArtifacts" > <li class="list-group-item border-bottom-0">{{artifact.title}}<span></span></li> <!-- 其他属性渲染 --> </ul> </div>
API响应示例
{ "id": 120081, "api_model": "artworks", "api_link": "https://api.artic.edu/api/v1/artworks/120081", "is_boosted": false, "title": "Landscape with Dog", "alt_titles": null, "thumbnail": { "lqip": "...", "width": 2721, "height": 2250, "alt_text": "A work made of oil on composition board." }, "main_reference_number": "1990.485", "date_start": 1832, "date_end": 1832, "artist_display": "Thomas Doughty\nAmerican, 1793–1856", "place_of_origin": "United States", "dimensions": "24.8 × 29.2 cm (9 3/4 × 11 1/2 in.)", "medium_display": "Oil on composition board", "inscriptions": "signed l.r.: \"TD/1832\"", "credit_line": "Through prior acquisition of the Charles H. and Mary F. S. Worcester Collection", "department_title": "Arts of the Americas" // 其他冗余字段省略 }
问题分析
- 数据类型不匹配:
allArtifacts声明为Artifact[]数组类型,但API返回的是单个Artifact对象,直接赋值会导致*ngFor无法遍历非可迭代对象,触发NG0900错误。 - 模型类型错误:模型中
id、main_reference_number、dimensions的类型与API返回值不匹配,会导致TypeScript类型校验警告及数据解析问题。 - 服务未指定返回类型:HTTP请求未声明返回类型,无法获得TypeScript类型推断支持,增加调试难度。
- 组件代码错误:
console.log(artifacts)引用未定义变量;isFetching赋值顺序颠倒,无法正确展示加载状态。
解决方案
根据需求分为两种场景处理:
场景1:获取单个艺术品数据
若API确实返回单个对象,无需使用*ngFor,直接绑定对象属性即可:
1. 修正组件代码
export class ArtifactCardComponent implements OnInit { allArtifact: Artifact | undefined; // 改为单个对象类型 isFetching: boolean = false; errorMessage: string = ''; constructor(private artifactService: ArtifactService) {} ngOnInit() { this.isFetching = true; this.artifactService.getArtifact().pipe( finalize(() => this.isFetching = false) // 请求完成后统一设置加载状态 ).subscribe({ next: (data) => { this.allArtifact = data; console.log(this.allArtifact); }, error: (err) => { this.errorMessage = err.message; } }); } }
2. 修正服务代码
public getArtifact(): Observable<Artifact> { return this.http.get<Artifact>(this.baseURL); // 指定返回单个Artifact类型 }
3. 修正视图代码
<div *ngIf="allArtifact; else loading"> <ul class="list-group list-group-flush d-flex align-items-start"> <li class="list-group-item border-bottom-0">{{allArtifact.title}}</li> <li class="list-group-item border-bottom-0">{{allArtifact.artist_display}}</li> <li class="list-group-item border-bottom-0">{{allArtifact.dimensions}}</li> <!-- 其他需要的属性 --> </ul> </div> <ng-template #loading> <p>加载中...</p> </ng-template>
场景2:获取艺术品列表数据
若实际需求是获取列表,需确认API调用的是列表接口(如/api/v1/artworks),该接口通常返回包含data数组的结构:
1. 修正模型代码(匹配API数据类型)
export class Artifact { id?: number; // 改为数字类型 title: string; date_start: number; date_end: number; artist_display: string; main_reference_number: string; // 改为字符串类型 place_of_origin: string; medium_display: string; inscriptions: string; dimensions: string; // 改为字符串类型 credit_line: string; department_title: string; }
2. 修正服务代码
// 定义API返回的列表结构类型 interface ArtifactListResponse { data: Artifact[]; // 其他可能的字段如pagination等 } public getArtifacts(): Observable<ArtifactListResponse> { return this.http.get<ArtifactListResponse>(this.baseURL); // 指定列表响应类型 }
3. 修正组件代码
export class ArtifactCardComponent implements OnInit { allArtifacts: Artifact[] = []; isFetching: boolean = false; errorMessage: string = ''; constructor(private artifactService: ArtifactService) {} ngOnInit() { this.isFetching = true; this.artifactService.getArtifacts().pipe( map(response => response.data), // 提取数组数据 finalize(() => this.isFetching = false) ).subscribe({ next: (data) => { this.allArtifacts = data; console.log(this.allArtifacts); }, error: (err) => { this.errorMessage = err.message; } }); } }
4. 视图代码保持不变(*ngFor可正常遍历数组)
额外优化建议
- 使用
async管道简化订阅管理,避免手动订阅导致的内存泄漏:
组件中改为:<div *ngIf="allArtifacts$ | async as artifacts; else loading"> <ul *ngFor="let artifact of artifacts"> <li>{{artifact.title}}</li> </ul> </div>allArtifacts$: Observable<Artifact[]>; ngOnInit() { this.allArtifacts$ = this.artifactService.getArtifacts().pipe( map(response => response.data) ); }
内容的提问来源于stack exchange,提问作者user2920627
相关产品推荐
相关产品推荐

