【发布时间】:2020-10-20 11:12:47
【问题描述】:
我想从 req.body 中的 ID 数组中获取每种产品的名称和价格,并将其保存在新模型中(付款),为此我遍历每种产品并查找其db (Product.findById) 中的 id 并将我需要的东西(名称和价格)保存为 arrayProducts 中的一个对象,但是 newPayment 是在 arrayProducts 完成填充之前创建的,我将它创建为空,因为我可以这样做newPayment 是在 forEach 产品完成后创建的?
router.post('/new/payment', async (req, res) => {
const date = Date.now();
const { amount, clientId, products, services, officeId } = req.body;
var arrayProducts = [];
products.forEach(function (product) {
var productFound = {};
Product.findById(product, function (err, result) {
if (err) {
res.status(404).send({ error: "Oh uh, something went wrong", err: err });
}
else {
productFound = { name: result.name, price: result.price };
arrayProducts.push(productFound);
console.log(arrayProducts);
}
})
});
console.log(arrayProducts);
const newPayment = new Payment({ amount, clientId, products: arrayProducts, services, officeId, date });
await newPayment.save((err) => {
if (err) {
res.status(404).send({ error: "Oh uh, something went wrong", err: err });
}
else {
res.status(201).send({ status: "Payment successful", id: newPayment._id });
}
});;
});
【问题讨论】:
-
您需要阅读有关 node.js 中的非阻塞、异步操作的信息。你的
Product.findById()是非阻塞和异步的,这意味着它的回调在你的整个路由处理程序完成执行之后被调用很长时间,当然在console.log(arrayProducts);和之后的所有代码之后。 -
您可能应该做的是将
products.forEach()更改为for (let product of products) { ... },为您的数据库使用Promise 接口并在该promise 上使用await,这样您就可以正确排序您的操作以及何时执行最后一个操作完成,然后执行其余代码。或者,您可以收集所有的 Promise 并使用Promise.all()跟踪它们何时完成。 -
仅供参考,如果您在代码的各个部分(循环前、循环内和循环后)放置独特的
console.log()语句,您将看到有缺陷的执行顺序。作为基本调试步骤,您应该学习如何自己做这件事。
标签: node.js mongoose async-await