Создать массив обещаний для будущего исполнения - PullRequest
0 голосов
/ 29 августа 2018

Я создал массив для хранения списка обещаний, которые должны запускаться после одного вызова Promise.all, однако сразу после помещения этого нового Promise в массив, который он выполняет. Как я могу это исправить?

let promises: any[] = [];

this.tasklistItems.forEach(element => {
  if (element.checked) {
     promises.push(new Promise(() => this.tasklistItemsService.delete(this.tasklist, element.id))); // It gets executed right after this line
  }
});

Promise.all(promises) // But I need to start executing here
  .then((res) => { // So I can get all responses at the same place, together
    this.notification.success('Success!', 'Rows removed.');
  },
  (err) => {
  });

UPDATE

Следуя советам @ Evert, теперь у меня есть следующий код:

  const deferred = [];
  this.tasklistItems.forEach(element => {
    if (element.checked) {
      deferred.push(() => this.tasklistItemsService.delete(this.tasklist, element.id).subscribe());
    }
  });

  Promise.all(deferred.map(func => func()))
    .then(
      () => {
        this.notification.success('Sucess!', 'Rows removed.');
        this.refreshGrid();
      },
      err => {
        console.log(err);
        this.notification.error('Error!', 'Could not remove the selected rows.');
      }
    );

А это мой сервис, использующий HttpClient:

  delete(tasklistId: number, id: number): Observable<boolean> {
    return this.http.delete(`${this.baseUrl}/${tasklistId}/items/${id}`)
      .pipe(catchError(this.handleError));
  }

Если я не добавлю subscribe() к вызову delete(...), он не будет выполнен, и если я добавлю его, refreshGrid() будет вызван до того, как произойдет удаление.

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

В общем, .forEach() и Promise.all() не очень хорошо сочетаются, и создание массивов отложенных обещаний добавляет некоторые ненужные шаги. ( Нолана Лоусона «У нас проблема с обещаниями» отлично справляется с обоими этими вопросами.) Как упоминалось в @Evert, это потому, что обещания «нетерпеливы» и выполняются, как только они построены.

Похоже, вы хотите взять массив, отсеять непроверенные опции, а затем разрешить массив обещаний из этого. Как насчет использования .filter() и .map() непосредственно в Promise.all()?

Promise.all(
  this.tasklistItems
    .filter(element => element.checked)
    .map(checkedElement => this.tasklistItemsService.delete(this.tasklist, checkedElement.id)
)
.then((res) => { // So I can get all responses at the same place, together
  this.notification.success('Success!', 'Rows removed.');
},
(err) => {});
0 голосов
/ 29 августа 2018

Эта строка прерывается:

new Promise(() => this.tasklistItemsService.delete(this.tasklist, element.id)

Кроме того, обещания обычно выполняются немедленно. Они не являются механизмом для отсрочки исполнения на более поздний момент. К счастью, в javascript есть нечто чрезвычайно простое: простая старая функция.

const deferred = [];
this.tasklistItems.forEach(element => {
  if (element.checked) {
    deferred.push(() => this.tasklistItemsService.delete(this.tasklist, element.id)));
  }
}

// Iterates over all stored functions, calls them all and returns the result as an array of promises.
Promise.all( deferred.map( func => func() ) );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...