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

Angular中如何动态填充嵌套数组结构的ProgramScorecardModel数组

问题:从.NET MVC转Angular开发,填充嵌套数组模型时出现TypeError错误

我从.NET MVC转Angular开发,需要创建和.NET中ProgramScorecardModel一致的嵌套数组结构数据模型,已经定义了对应的TypeScript接口,但用forEach结合async/await填充数据时,出现TypeError: Cannot set properties of undefined (setting 'programId')错误。proglist是包含programId、programName、reportingdate的数组,求正确的填充方法。


.NET数据模型代码

public class ProgramScorecardModel
{
    public string programId { get; set; }
    public DateTime? reportingDate { get; set; }
    public string programName { get; set; }
    public IList<AB_ViewModel> AB_ViewModel { get; set; }
    public IList<CD_ViewModel> CD_ViewModel { get; set; }
}

public class AB_ViewModel
{
    public string rating { get; set; }
    public DateTime? reportingDate { get; set; }
    public string comments { get; set; }
}
public class CD_ViewModel
{
    public string rating { get; set; }
    public DateTime? reportingDate { get; set; }
    public string comments { get; set; }
}

TypeScript接口代码

interface ProgramScorecardModel {
    programId: string;
    reportingDate: string;
    programName: string;
    AB_ViewModel: AB_ViewModel[];
    CD_ViewModel: CD_ViewModel[];
}

interface AB_ViewModel {
    rating: string;
    reportingDate: string;
    comments: string;
}
interface CD_ViewModel {
    rating: string;
    reportingDate: string;
    comments: string;
}

出错的填充代码

let ProgramScorecard: ProgramScorecardModel[]=[]
proglist.forEach(async (p, index) => {
    ProgramScorecard[index].programId = p.programId;
    ProgramScorecard[index].programName = p.programName;

    let AB_data = await this.GetMeasureForScorecard(p.programid,reportingdate);
    let CD_Data= await this.GetMeasureForScorecard(p.programid,reportingdate);
    
    ProgramScorecard[index].AB_ViewModel= AB_data ;
    ProgramScorecard[index].CD_ViewModel = CD_Data;
    
});

解决方案

错误原因

  1. ProgramScorecard是初始空数组,ProgramScorecard[index]一开始是undefined,直接给它的属性赋值必然触发错误。
  2. forEach不支持async/await的串行执行逻辑,会导致所有异步请求同时发起,且无法统一等待所有操作完成。

正确填充方法

方法1:使用map+Promise.all(推荐)

map返回每个元素对应的Promise,Promise.all等待所有异步操作完成,同时创建完整的数组元素:

async function fillScorecardData() {
    const ProgramScorecard: ProgramScorecardModel[] = await Promise.all(
        proglist.map(async (p) => {
            // 获取异步数据
            const abData = await this.GetMeasureForScorecard(p.programId, p.reportingdate);
            const cdData = await this.GetMeasureForScorecard(p.programId, p.reportingdate);
            
            // 返回完整的模型对象
            return {
                programId: p.programId,
                programName: p.programName,
                reportingDate: p.reportingdate,
                AB_ViewModel: abData,
                CD_ViewModel: cdData
            };
        })
    );
    // 此处可直接使用填充好的ProgramScorecard数组
}

方法2:用for...of替代forEach(串行执行场景)

如果需要按顺序执行异步请求,用for...of可以天然支持await:

async function fillScorecardData() {
    const ProgramScorecard: ProgramScorecardModel[] = [];
    for (const p of proglist) {
        const abData = await this.GetMeasureForScorecard(p.programId, p.reportingdate);
        const cdData = await this.GetMeasureForScorecard(p.programId, p.reportingdate);
        
        const scorecardItem: ProgramScorecardModel = {
            programId: p.programId,
            programName: p.programName,
            reportingDate: p.reportingdate,
            AB_ViewModel: abData,
            CD_ViewModel: cdData
        };
        ProgramScorecard.push(scorecardItem);
    }
    // 使用填充后的数组
}

额外优化点

  1. TypeScript接口中把AB_ViewModel/CD_ViewModel的类型从any改为对应数组类型,获得类型检查的语法提示和错误预警。
  2. 注意变量名大小写一致性:原代码中p.programid应为p.programId,和.NET模型字段保持一致,避免属性未定义的问题。
  3. 如果AB和CD的数据源逻辑不同,要确保调用对应的接口,避免重复调用同一个接口。

内容的提问来源于stack exchange,提问作者FlyFish

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 02:35:25