【发布时间】:2021-02-27 14:45:58
【问题描述】:
我想在客户完成订单后向他们发送一封订单确认电子邮件(带有 nodemailer)。
在这封确认邮件中,我想插入一些购买产品的数据。
我使用了许多 async/await 组合,但没有一个成功。
我现在得到的代码:
async function getProductData(products) {
let productsArray = products;
try {
let productsHtml = "";
for await (const product of productsArray) { // loop through the products
db.collection("collectionname").findOne(query, (err, data) => { // get data for every product
if (err) console.log(err)
else {
let productHtml = `<p>productname: ${data.productname}</p>
<img src="${data.imageSrc}">`;
productsHtml += productHtml; // add the product html string to productsHtml
}
})
}
} catch (error) {
console.log(error);
}
return productsHtml; //return the productsHtml string. But it returns "", because it doesn't await the mongodb function
}
async function sendConfirmationMail() {
let productsHtml = await getProductData(products); //"products" is an array
//nodemailer code
let transporter = nodemailer.createTransport({
// configuration
});
let email = await transporter.sendMail({
//email information
html: `<p>Thank you for your order!</p>
${productsHtml}`;, // insert the html string for all products into the mail
});
}
问题是getProductData() 中的 return 语句在 for 循环完成之前触发。然后返回 undefined。
有人对我如何在这里以正确的方式实现 async/await 有提示吗?
【问题讨论】:
-
仅仅是因为您没有等待数据库调用。您正在向它传递一个回调,因此它不会返回 Promise 并异步解析。只需
await并删除回调。 -
@JeremyThille 我已将 await 添加到 db 调用中(仍然返回未定义)。但是你的意思是删除什么回调? getProductData() 回调?
-
.findOne(query, (err, data) => {这有一个回调。您将一个函数作为第二个参数传递给它,它将(err,data)作为它自己的参数。您需要删除此回调并将async/await语法与try/catch一起使用。类似const data = await db.collection("collectionname").findOne(query); -
另一方面,您不需要
for await (const product of productsArray)。您正在迭代一个静态值数组,而不是一个 Promises 数组。删除此await。 -
@JeremyThille 谢谢!现在可以了。感谢帮助
标签: javascript node.js mongodb async-await