Угловой 7 - Ожидание завершения цикла обработки - PullRequest
0 голосов
/ 03 октября 2019

У меня есть угловая сущность Z, одним из свойств которой является список другой сущности Y, мне нужно удалить сущность Z, а когда я это делаю, мне нужно удалить список сущности Yвнутри него. Проблема в том, что сначала мне нужно удалить все значения Y, а затем удалить Z из-за проблем с FK в базе данных. Мой метод следующий:

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, а затем поставитьawait в методе onDelete, но он не работает

Как я могу сначала удалить все Y, а после его завершения удалить все Z?

Ответы [ 3 ]

1 голос
/ 03 октября 2019

попробуйте использовать обещание в этом потоке, используя оператор then в функции delete. так что только после завершения for он вернет

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(() => {
      });
    }
  })

}
1 голос
/ 03 октября 2019

Это можно сделать, используя внешнюю функцию async / await, или вы можете использовать новую для ... итерации (как вы делаете сейчас).

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

Но, честно говоря,если у вас есть доступ к BE, я бы немного изменил ваш подход. Вместо того, чтобы делать forEach или for ... или любую другую итерацию, вы должны использовать bulkDelete. Таким образом вы сохраните несколько запросов к вашему BE и несколько исполнений БД :). Примерно так:

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, вы будете делать только 1 удаление, выполняя где в (1, 2, 3, 4). , n) вместо выполнения 1 запроса и 1 удаления для каждого из элементов Y.

0 голосов
/ 03 октября 2019

Всякий раз, когда у вас есть циклы for или для каждого цикла с асинхронным действием внутри них внутри Javascript, они могут вместо этого бросить ВАС за цикл, потому что они не ведут себя точно так, как большинство ожидают - в большинстве случаев цикл 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 и как это сделать в методологии реагирования.

...