如何映射.find()返回的数据?

时间:2019-04-07 20:20:08

标签: javascript node.js mongodb mongoose

我有一个简单的功能:

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返回对象,如果我console.log返回,则它是一个复杂的Query对象。

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

1 个答案:

答案 0 :(得分:1)

首先,Users.find()是一个异步操作,因此oldUsers始终是不确定的。您需要await(如果您没有使用promise,则必须使用回调)。

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

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

通常,在映射异步操作时,您应该使用Promise.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,其值将是一个包含整个映射结果的数组。