You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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"
  // 其他冗余字段省略
}

问题分析

  1. 数据类型不匹配:allArtifacts声明为Artifact[]数组类型,但API返回的是单个Artifact对象,直接赋值会导致*ngFor无法遍历非可迭代对象,触发NG0900错误。
  2. 模型类型错误:模型中id、main_reference_number、dimensions的类型与API返回值不匹配,会导致TypeScript类型校验警告及数据解析问题。
  3. 服务未指定返回类型:HTTP请求未声明返回类型,无法获得TypeScript类型推断支持,增加调试难度。
  4. 组件代码错误: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 17:55:14