一旦多个嵌套的forEach循环中的所有异步操作完成,如何解决promise?

时间:2018-06-06 15:35:04

标签: javascript

我在异步函数中有一个forEach循环,而在forEach中有另外两个执行AJAX请求的forEach循环。一旦所有的AJAX请求都完成,我想返回一个已解决的promise。

首先,用户点击“提交”,我调用一个函数来处理提交,将submitting属性设置为true。提交完成后,我想更改submitting属性的值。

submit() {
  this.submitting = true;

  if (creating) {
    this.create().then(() => this.submitting = false)
  }
}

以下是create()方法的近似值:

async create() {

  // Calls a function that uses axios to send a POST request to create
  // a new group, returning its ID upon completion. This works fine.
  const groupId = await this.createGroup();

  // 'users' is an array of objects
  this.users.forEach(async user => {

    // Create a new user and get their ID. This works fine.
    const userId = await this.createUser(info);

    // Each 'user' object contains a key called 'attributes' whose 
    // value is an array of 'attribute' objects. I use axios to make a 
    // POST request to store the info about these attributes in the DB.
    user.attributes.forEach(attribute => {
      axios.post('/attributes', attribute)

      // In my application, I'm actually calling a method that handles
      // making the request, so it looks more like this: 
      // this.createAttributes(attribute)
    }

    // Each 'user' object also contains a key called 'images' whose 
    // value is an array of 'image' objects. Here again, I use axios to 
    // make a POST request to store the info about these images.
    user.images.forEach(image => {
      axios.post('/images', image)
    }

  }

  // Once everything has successfully posted, I want to return a 
  // resolved promise so that the then() callback on my create method
  // is executed. However, anything here gets executed before the AJAX
  // requests complete.
  console.log('All done');

}

我尝试了一些不同的解决方案,我使用map()捕获承诺,并在完成后使用Promise.all执行回调,但我没有成功。我认为这个问题源于我有多个嵌套的forEach()循环,但是我不明白承诺(以及它们在forEach()循环中的行为),以便确定。

我的理解是我可以在await循环中使用for...of,但如果可能的话,我宁愿并行执行AJAX请求。

谢谢!

编辑:建议的副本类似,但我的问题是关于嵌套 forEach循环中的异步操作。虽然解决方案显示处理这些案例没有什么特别独特的(在父循环和嵌套循环上都做同样的事情),但确定是否是这种情况是提出问题的动机。

1 个答案:

答案 0 :(得分:1)

map承诺,然后使用Promise.all并等待它们:

await Promise.all(user.images.map(image =>
  axios.post('/images', image)
));

同样适用于主要的forEach:

await Promise.all(this.users.map(async user => {
  //...
}));