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

Angular构建模拟数据时的循环类引用问题求解

解决Angular模拟数据中的循环引用问题

方法1:先创建实例,后补全关联关系

JavaScript/TypeScript中对象是引用类型,你可以先分别创建Company和Application实例,再互相补充关联属性,完美避开循环依赖问题。

调整CompanyService

export class CompanyService {
  companies: Company[] = [];

  constructor(private http: HttpClient) {
    // 先创建公司实例
    const company1 = new Company(1, 'Company 1', []);
    const company2 = new Company(2, 'Company 2', []);

    // 创建应用实例并关联对应公司
    const app1 = new Application(1, 'Application 1', company1);
    const app2 = new Application(2, 'Application 2', company1);
    const app3 = new Application(3, 'Application 3', company2);

    // 把应用添加回公司的applications数组
    company1.applications.push(app1, app2);
    company2.applications.push(app3);

    this.companies = [company1, company2];
  }

  getAll(): Company[] {
    return this.companies;
  }

  findById(id: number): Company | undefined {
    return this.companies.find(company => company.id === id);
  }
}

调整ApplicationService

可以直接从CompanyService中获取已关联好的应用:

export class ApplicationService {
  applications: Application[] = [];

  constructor(private http: HttpClient, private companyService: CompanyService) {
    // 从所有公司中收集应用
    this.applications = this.companyService.companies.flatMap(company => company.applications);
  }

  getAll(): Application[] {
    return this.applications;
  }

  findById(id: number): Application | undefined {
    return this.applications.find(application => application.id === id);
  }
}

方法2:改用接口定义数据结构(更轻量化)

如果你的类仅用于定义数据结构、没有额外业务方法,用接口替代会更简洁,同样能处理循环引用:

定义接口

export interface Company {
  id: number;
  name: string;
  applications: Application[];
}

export interface Application {
  id: number;
  name: string;
  company: Company;
}

服务中初始化数据

export class CompanyService {
  companies: Company[] = [];

  constructor(private http: HttpClient) {
    const company1: Company = { id: 1, name: 'Company 1', applications: [] };
    const company2: Company = { id: 2, name: 'Company 2', applications: [] };

    const app1: Application = { id: 1, name: 'Application 1', company: company1 };
    const app2: Application = { id: 2, name: 'Application 2', company: company1 };
    const app3: Application = { id: 3, name: 'Application 3', company: company2 };

    company1.applications = [app1, app2];
    company2.applications = [app3];

    this.companies = [company1, company2];
  }

  // 其他方法保持不变
}

方法3:给类添加关联设置方法(可选)

如果必须保留类,且希望构造时不强制传入完整关联,可以修改类,添加方法后期设置双向关联:

修改类定义

export class Company {
  public id: number;
  public name: string;
  public applications: Application[] = [];

  constructor(id: number, name: string) {
    this.id = id;
    this.name = name;
  }

  addApplication(app: Application) {
    this.applications.push(app);
    // 自动同步应用的company属性
    if (app.company !== this) {
      app.setCompany(this);
    }
  }
}

export class Application {
  public id: number;
  public name: string;
  public company: Company | undefined;

  constructor(id: number, name: string) {
    this.id = id;
    this.name = name;
  }

  setCompany(company: Company) {
    this.company = company;
    // 自动同步公司的applications数组
    if (!company.applications.includes(this)) {
      company.addApplication(this);
    }
  }
}

服务中初始化

export class CompanyService {
  companies: Company[] = [];

  constructor(private http: HttpClient) {
    const company1 = new Company(1, 'Company 1');
    const company2 = new Company(2, 'Company 2');

    const app1 = new Application(1, 'Application 1');
    const app2 = new Application(2, 'Application 2');

    // 调用任一方法即可自动完成双向关联
    app1.setCompany(company1);
    company2.addApplication(new Application(3, 'Application 3'));

    this.companies = [company1, company2];
  }

  // 其他方法保持不变
}

内容的提问来源于stack exchange,提问作者A. Vreeswijk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 21:37:39