首页 > 解决方案 > For循环和地图差异

问题描述

我有两个案例,我试图了解发生了什么,但对我来说仍然不够清楚,所以我读到如果我想在 for 循环或 map 中运行异步调用,我需要使用 Promise.all 但让我分享发生了什么与我一起

首先,我使用 map 更新数据库中的许多记录,它更新了一些而不是全部数据

AllAuthToken.map(async singleToken =>{
          let deviceIds = uuidv4();
        let newDeviceArray = {
          [deviceIds]: singleToken.deviceToken,
        };
        await AuthToken.updateOne(
          { _id: singleToken._id },
          {
            $set: {
              tokensDeviceArray: [newDeviceArray],
              deviceId: [deviceIds],
            },
          },
          { $new: true }
        );
}

然后发生这种情况后,我使用了 for 循环并更新了所有数据

  for (let i = 0; i < AllAuthToken.length; i++) {
    let deviceIds = uuidv4();
    let newDeviceArray = {
      [deviceIds]: AllAuthToken[i].deviceToken,
    };
    await AuthToken.updateOne(
      { _id: AllAuthToken[i]._id },
      {
        $set: {
          tokensDeviceArray: [newDeviceArray],
          deviceId: [deviceIds],
        },
      },
      { $new: true }
    );
  }

那么发生了什么导致第一个案例失败而第二个案例通过

标签: javascriptarraysmongodbes6-promise

解决方案


原因是.map它一个接一个地执行它的回调而不等待。做它的await事,但这只会延迟之后的代码await。但它不会阻止.map迭代继续下一次调用回调,因为它不是发生的async函数的一部分await

for另一方面,循环是与发生的地方相同的函数的一部分,因此 async迭代await仅在等待的承诺解决时才会继续。

如果您希望以“并行”方式执行数据库请求,即在不等待前一个请求解决的情况下启动下一个请求,则使用Promise.all,如下所示:

let promises = AllAuthToken.map(singleToken => {
    let deviceIds = uuidv4();
    let newDeviceArray = {
        [deviceIds]: singleToken.deviceToken,
    };
    return AuthToken.updateOne(
        { _id: singleToken._id },
        {
            $set: {
                tokensDeviceArray: [newDeviceArray],
                deviceId: [deviceIds],
            },
        },
        { $new: true }
    );
};

await Promise.all(promises);
/* ... now all is done ... */

推荐阅读