首页 > 解决方案 > 如何映射`.find()`返回的数据?

问题描述

我有一个简单的功能:

const oldUsers = Users.find(
   {
      isReminded: false,
      creationDate: {
         "$lt": new Date(Date.now() - thirtyDays),
      },
   },
);

接着:

export const notifyOldUsers = () => 
   Array.isArray(oldUsers) ? oldUsers.map(async(user, i) => {
      await Users.updateOne({ _id: user._id }, { "$set": { isReminded: true }});

      await transporter.sendMail(sendMail));
   }) : [];
};

但问题是oldUsers返回object,如果我console.log这样做,它会很复杂Query对象。

问题:如何正确循环.find()产生的数据?

标签: javascriptnode.jsmongodbmongoose

解决方案


首先,这Users.find()是一个异步操作,所以oldUsers总是未定义的。您需要await它(如果您不使用承诺,则必须使用回调)。

const oldUsers = await Users.find(...)

其次,您的notifyOldUsers函数不是异步的,因此它会运行映射函数,但会立即退出,而不是等待映射的异步操作完成。

通常,在映射异步操作时,您应该使用 aPromise.all()来收集回调函数返回的所有 Promise 并等待它们全部解决。

export const notifyOldUsers = async () => {
  const promises = oldUsers.map(async (user) => {
    await Users.updateOne({ _id: user._id }, { "$set": { isReminded: true }})
    await transporter.sendMail(sendMail))
  })

  return Promise.all(promises)
}

我故意将映射从 中分离出来,Promise.all()以说明返回的承诺映射。这可以进一步优化为以下内容。

export const async notifyOldUsers = async () => {
  return Promise.all( oldUsers.map(async (user) => {
    await Users.updateOne({ _id: user._id }, { "$set": { isReminded: true }})
    await transporter.sendMail(sendMail))
  }) )
}

在这两种情况下,这个异步函数都会返回一个新的 Promise,它的值将是一个包含整个地图结果的数组。


推荐阅读