【问题标题】:push in forEach not working with async function推入 forEach 不适用于异步功能
【发布时间】:2021-11-03 07:13:51
【问题描述】:

所以我试图将对象推入一个数组。如果我 console.log() 对象被打印到控制台。所以它们不是未定义的。但是如果我尝试推送它们,它会显示:“错误:未捕获(承诺):TypeError:无法读取未定义的属性(读取'推送')”。

这是我的代码:

let snapProtections = JSON.parse(snapshot.protection);
this.completeMachine.operationModes = snapOperationModes;
        snapProtections.forEach(async prot => {
          this.test.push(await this.protectionDataAcessService.getProtectionAndOperationModesByProtectionId(prot.id));
        });

test 是 ProtectionAndOperationModes 类型的数组:

export interface ProtectionAndOperationModes {
    protection: Protection;
    operationModes: OperationMode[];
    image?: EntityImage;
}

这是 getProtectionAndOperationModesByProtectionId 函数:

public async getProtectionAndOperationModesByProtectionId(protectionId: string): Promise<ProtectionAndOperationModes> {
    const protection = await this.protectionService.getById(protectionId);
    return await this.getOperationModesOfProtection(protection);
  }

private async getOperationModesOfProtection(protection: Protection): Promise<ProtectionAndOperationModes> {
    const availableOperationModes = await this.operationModeService.getByMachineId(protection.machineId);
    const linkedOperationModes = await this.protectionLinkService.getByProtectionId(protection.id);
    const image = await this.imageService.getByEntityId(protection.id);
    return {
      protection: protection,
      operationModes: availableOperationModes.filter(o => linkedOperationModes.find(l => l.operationModeId === o.id)),
      image: image
    };
  }

对如何将对象放入数组有任何帮助吗?

【问题讨论】:

  • 似乎this.testbis 不是数组但未定义...
  • 这是一个常见的错误和常见的问题。您不能在同步 Array 方法(map、filter、forEach 等)中使用await。它不起作用(不等待)。您必须改用for 循环。

标签: javascript angular typescript


【解决方案1】:

好的,所以我只是跳转到您的代码,并没有完全阅读到您遇到的错误是推送到一个不存在的数组。我会留下原来的,因为这将是一个后续问题:)

您的 this.test 变量未定义,因此您无法推送到它。您可以通过不推送它而是直接分配变量来解决这个问题 - 或者通过确保它事先存在。 在我最初的回答中,我还展示了一种可以做到这一点的方法(代码的最后一行)。

原答案

您的代码确实有效 - 只是不是以您期望的方式。推送是异步发生的,因此您很可能过早观察到它。

要等到你的数组被填满,你必须像这样等待你的所有承诺:

let snapProtections = JSON.parse(snapshot.protection);
this.completeMachine.operationModes = snapOperationModes;

// protectionModes will contain an array of the resolved promises values
const protectionModes:ProtectionAndOperationModes[] = await Promise.all(
   // map the prots to an array of promises and await that array using promise.all
   snapProtections.map(prot => this.protectionDataAcessService.getProtectionAndOperationModesByProtectionId(prot.id))
);

protectionModes.forEach(mode => this.test.push(mode)); 
// or use spread: 
this.test.push(...protectionModes);
// or just assign to it
this.test = protectionModes;

这样,您的数据将在此代码之后填充。

【讨论】:

  • this.test = protectionModes; 尝试过,出现此错误:类型'[未知,未知,未知,未知,未知,未知,未知,未知,未知,未知]' 不可分配给类型'ProtectionAndOperationModes []'。类型“{}”缺少“ProtectionAndOperationModes”类型中的以下属性:保护、操作模式我这样定义我的数组:test: ProtectionAndOperationModes[];
  • 你的 this.test 定义了吗?例如。如果你执行“console.log(this.test)”,它会打印一个空数组吗?
  • 但是protectionModes.forEach(mode =&gt; this.test.push(mode)); 基本上将protectionModes 复制到this.test...?为什么不直接做this.test = await Promise.all(...)?无论如何,这个答案显然值得一票
  • @JeremyThille 这对我有用!谢谢!
  • @JeremyThille 这是代码的最后一行,我使用了一个中间变量来显示不同的方式——复制部分是基于他可能想要改变数组而不是覆盖它的假设。当然,你可以直接赋值给它,很好的提示! :)
猜你喜欢
  • 1970-01-01
  • 2019-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-27
相关资源
最近更新 更多