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 以及如何以反应式方法做到这一点。
我有一个 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 以及如何以反应式方法做到这一点。