Angular 7 - 等待函数完成处理循环

Angular 7 - Await for function to finish processing loop

我有一个 angular 实体 Z,它的一个属性是另一个实体 Y 的列表,我需要删除实体 Z,当我这样做时我需要删除其中的实体 Y 列表。问题是首先我需要删除所有 Y 值,然后由于数据库的 FK 问题删除 Z。我的方法如下:

onDelete(id: number, name: string, Y: Y[]) {
    this.deleteYInZ(Y);
    this.ZService.deleteZ(this.selectedSecuritySubject.value, id).subscribe(() => {
      this.getAllZ();
      }
  }

deleteYInZ 是:

 deleteYInZ(Y: Y[]) {
    for (const Yentity of Y) {
      this.targetService.deleteTarget(this.selectedSecuritySubject.value, Yentity .ID).subscribe(() => {
      });
    }
  }

我这里有一个 async 问题 我尝试执行异步 deleteYInZ 然后在 onDelete 方法上放置一个 await 但它不起作用

如何才能先删除所有 Y,然后删除所有 Z

这可以通过使用外部 async/await 函数来完成,或者您可以使用新的 for...of 迭代(就像您现在正在做的那样)。

for (const theY of Y) {
  await yourDeleteFunction(theY);
}

但是,老实说,如果您可以访问 BE,我会稍微改变一下您的方法。您应该使用 bulkDelete,而不是执行 forEach 或 for...of 或任何其他迭代。这样,您将保存一些对 BE 的请求和一些 DB 执行 :)。像这样:

deleteZInz(id: number, name: string, items: Y[]) {
  this.deleteYInz(items)
    .subscribe(result => {
      this.ZService.deleteZ(...etc);
    });
}

deleteYInz(items: Y[]): Observable<yourReturnType> {
  return this.targetService.deleteBulk(
    this.selectedSecuritySubject.value,
    items.map(item => item.id),
  );
}

这样,假设您有一个 MySQL 数据库,您将通过执行 where in (1, 2, 3, 4 , n) 而不是对每个 Y 项目执行 1 个请求和 1 个删除。

尝试在此流程中使用承诺,在删除函数中使用 then 运算符。 所以只有在 for 终止后才会 return

onDelete(id: number, name: string, Y: Y[]) {
this.deleteYInZ(Y).then(_ => {
    this.ZService.deleteZ(this.selectedSecuritySubject.value, id).subscribe(() => {
    this.getAllZ();
  });

}

deleteYInZ(Y: Y[]) {
  return Promise.resolve().then(function () {
    for (const Yentity of Y) {
      this.targetService.deleteTarget(this.selectedSecuritySubject.value,Yentity.ID).subscribe(() => {
      });
    }
  })

}

只要你在 Javascript 中有 for 循环或 for each 循环,其中有一个异步操作,它们就会让你 for a 循环,因为它们的行为并不像大多数人预期的那样——在大多数情况下,for 循环将在异步操作之前完成。我会尝试以下操作(希望至少能让您走上正轨):

async onDelete(id: number, name: string, Y: Y[]) {
    await this.deleteYInZ(Y);
    ...
}

async deleteYInZ(Y: Y[]) {
    await this.asyncForEach(Y, async (Yentity) => {
        await this.targetService.deleteTarget(this.selectedSecuritySubject.value, Yentity.ID);
    });
}

async asyncForEach(array, callback) {
    for (let index = 0; index < array.length; index++) {
        await callback(array[index], index, array);
    }
}

另一方面,您不应该订阅所有内容,尤其是内部可观察循环,而是使用 mergeMap 等工具将其管道化并返回可观察对象(您应该这样做,以便只有调用者订阅,否则您可能运行 进入其他问题,例如奇怪的行为和内存泄漏)。这超出了这个问题的范围,但我会更多地研究 rxjs 以及如何以反应式方法做到这一点。