【问题标题】:Create array of promises for future execution为未来执行创建一系列承诺
【发布时间】:2018-08-30 00:43:48
【问题描述】:

我创建了一个数组来存储应在单次调用 Promise.all 后运行的 Promise 列表,但是在将这个新的 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) => {
  });

更新

按照@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()

【问题讨论】:

    标签: angular typescript promise


    【解决方案1】:

    这条线断了:

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

    除此之外,promise 通常会立即执行。它们不是一种将执行推迟到以后的机制。值得庆幸的是,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() ) );
    

    【讨论】:

    • 成功了。但是现在this.tasklistItemsService.delete 需要显式调用 subscribe() 才能执行。我会更新问题中的代码。
    • @JulianoNunesSilvaOliveira 这不再是我可以帮助的事情,因为它现在(我认为)是一个角度问题,而不是一个通用的 javascript + promises 问题。我会说,如果你现在需要subscribe,我想你以前也需要它。
    • 通过使用 toPromise 转换 HttpClient.delete 返回并删除 subscribe() 解决了另一个错误。
    • 这是有道理的。我没有意识到delete() 默认没有返回承诺
    • 它返回一个Observable。现在一切都按我的需要工作。谢谢。
    【解决方案2】:

    一般来说,.forEach()Promise.all() 不能很好地混合,并且创建延迟承诺的数组会增加一些不必要的步骤。 (Nolan Lawson 的"We have a problem with promises" 很好地解决了这两个问题。)正如@Evert 所提到的,这是因为promise 是“急切的”,并且一旦构建就执行。

    看起来您想要获取一个数组,筛选出未选中的选项,然后从中解析一组承诺。在Promise.all() 中直接使用.filter().map() 怎么样?

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

    【讨论】:

      猜你喜欢
      • 2016-02-01
      • 2018-04-28
      • 2013-12-04
      • 1970-01-01
      • 1970-01-01
      • 2018-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多