【问题标题】:Wait for array.map iterations in Promise.all [duplicate]等待 Promise.all 中的 array.map 迭代 [重复]
【发布时间】:2021-03-17 21:56:39
【问题描述】:

如果客户不存在,我有以下代码应该为客户添加项目。执行应该是并行的。

await Promise.all(
    customers.map(async (customer) => {
        return customer.items.map(async (item) => {
            return new Promise(async (resolve) => {
                const productExists = someArray.some(
                    (arrayValue) => arrayValue === item.id
                );
                if (!productExists) {
                    logger.info(
                    `customer item ${item.id} does not exist, creating...`
                    );
                    await createCustomerItem(item.id);
                    logger.info(`customer item ${item.id} created.`);

                    someArray.push(item.id);
                } else {
                    logger.info(`customer item ${item.id} already exists, skipping...`);
                }
                resolve(true);
            });
        });
    })

);

logger.info(`All items should now be present`);

问题是在!productExists)的情况下执行不是等待createCustomerItem解决

这是日志

customer item 32310 does not exist, creating...
customer item ao does not exist, creating...
customer item ute does not exist, creating...
All items should not be present
customer item ao created.
customer item ute created.
customer item 32310 created.

All items should not be present 当然应该排在最后。

当所有项目都已存在时,该过程看起来不错。

【问题讨论】:

  • map 对承诺一无所知。所以很遗憾,您不能以这种方式使用地图。
  • 我会说这是因为 Promise.all 需要一个 Promise 数组,而您正在向它传递一个 Promise 数组数组。改用 flatMap。
  • 我认为@JulienD 在他们的评论中提到的内容将解决您的问题。
  • ... 或简单地将return customer.items.map() 替换为return Promise.all(customer.items.map())

标签: javascript node.js asynchronous promise


【解决方案1】:

你可以这样做

const fruitsToGet = ['apple', 'grape', 'pear']

const mapLoop = async () => {
  console.log('Start')

  const promises = await fruitsToGet.map(async fruit => {
    const numFruit = new Promise((resolve, reject) => {
      setTimeout(() => resolve(fruit), 1000)
    });
    return numFruit
  })
  const numFruits = await Promise.all(promises)
  console.log(numFruits)

  console.log('End')
}

mapLoop();

结果

Start
["apple", "grape", "pear"]
End

sourcedemo

【讨论】:

    【解决方案2】:

    试试flatMap:

    await Promise.all(
        customers.flatMap(async (customer) => {
            return customer.items.map(async (item) => {
    

    它不会返回一个 Promises 数组,而是将内容展平为一个简单的 Promises 数组,这正是 Promise.all 所期望的。

    注意从您的问题中看不出是否需要保留每个客户的项目分组。如果是这样,请注意此解决方案会将数据结构更改为扁平列表,因此您会丢失分组。在您的items 中添加一些customerId,或者在cmets 中尝试@blex 的建议。

    【讨论】:

      猜你喜欢
      • 2020-04-25
      • 1970-01-01
      • 2016-12-06
      • 2019-05-16
      • 1970-01-01
      • 2020-12-21
      • 1970-01-01
      • 2020-04-28
      • 2020-11-01
      相关资源
      最近更新 更多