我有一个名为/ orderRegistration的“下订单”按钮,该按钮又会根据订单更新库存产品的数量,并将确认的订单发送到电子邮件中
const orderStatus = ['Confirmed', 'Not confirmed'];
router.post('/orderRegistration', (req, res) => {
if (req.session.successAuthentication === true &&
req.session.isWorker === false) {
conn.query(`SELECT orders.id,
products.product_id,
products.product_name,
products.product_amount,
order_product.count
FROM orders INNER JOIN order_product
ON orders.id = order_product.order_id INNER JOIN products
ON order_product.product_id = products.product_id
WHERE orders.id IN(
SELECT id
FROM orders
WHERE user_id=${req.session.userId}
AND status = '${orderStatus[1]}')
AND orders.status = '${orderStatus[1]}';`, (err, selProductId) => {
if (err) {throw err;}
if (selProductId.length > 0) {
let dateNow = new Date();
let prepDate = {
day: (dateNow.getDate() < 10) ? `0${dateNow.getDate()}` : dateNow.getDate(),
month: ( dateNow.getMonth() + 1 < 10) ? `0${dateNow.getMonth() + 1}` : dateNow.getMonth() + 1,
year: dateNow.getFullYear(),
hours: (dateNow.getHours() < 10) ? `0${dateNow.getHours()}` : dateNow.getHours(),
minutes: (dateNow.getMinutes() < 10) ? `0${dateNow.getMinutes()}` : dateNow.getMinutes()
};
let orderDate = `${prepDate.day}.${prepDate.month}.${prepDate.year} ${prepDate.hours}:${prepDate.minutes}`;
let productsInOrderHTML = '';
let totalAmount = 0;
for (let i = 0; i < selProductId.length; i++) {
conn.query(`UPDATE products
SET products.product_count_stock = products.product_count_stock - ${selProductId[i].count}
WHERE products.product_id = ${selProductId[i].product_id}`, err => {
if (err) {throw err;}
productsInOrderHTML += `<tr>
<td>
${selProductId[i].product_name}
</td>
<td>
${selProductId[i].count}
</td>
<td>
${selProductId[i].product_amount}
</td>
</tr>`;
totalAmount += selProductId[i].count *
selProductId[i].product_amount;
if(i === selProductId.length - 1) {
console.log('totalAmount: ' + totalAmount);
}
});
}
} else {
res.send('error');
}
});
} else {
res.send('error');
}
});
但是因为调用是异步的,所以有时循环没有时间更新所有产品并且发生了
if(i === selProductId.length - 1) {
console.log('totalAmount: ' + totalAmount);
}
也就是说,有时totalAmount可能有时间更新所有产品,有时却没有,并且事实证明totalAmount不会等于用户订购产品的成本。
我该如何重写查询或对其进行重构,以免再次发生这种情况
P.S。对不起英语,我是通过翻译翻译的,因为我会说俄语。我可能也错过了一些东西,因此如有必要请纠正我
答案 0 :(得分:1)
对数据库的查询是异步的,这意味着nodejs的事件循环会将它们传递到队列中,并且循环将继续进行,因此您必须等待它们
尝试
const orderStatus = ['Confirmed', 'Not confirmed'];
router.post('/orderRegistration', async (req, res) => {
if (req.session.successAuthentication === true &&
req.session.isWorker === false) {
await conn.promise().query(`SELECT orders.id,
products.product_id,
products.product_name,
products.product_amount,
order_product.count
FROM orders INNER JOIN order_product
ON orders.id = order_product.order_id INNER JOIN products
ON order_product.product_id = products.product_id
WHERE orders.id IN(
SELECT id
FROM orders
WHERE user_id=${req.session.userId}
AND status = '${orderStatus[1]}')
AND orders.status = '${orderStatus[1]}';`, async (err, selProductId) => {
if (err) {
throw err;
}
if (selProductId.length > 0) {
let dateNow = new Date();
let prepDate = {
day: (dateNow.getDate() < 10) ? `0${dateNow.getDate()}` : dateNow.getDate(),
month: (dateNow.getMonth() + 1 < 10) ? `0${dateNow.getMonth() + 1}` : dateNow.getMonth() + 1,
year: dateNow.getFullYear(),
hours: (dateNow.getHours() < 10) ? `0${dateNow.getHours()}` : dateNow.getHours(),
minutes: (dateNow.getMinutes() < 10) ? `0${dateNow.getMinutes()}` : dateNow.getMinutes()
};
let orderDate = `${prepDate.day}.${prepDate.month}.${prepDate.year} ${prepDate.hours}:${prepDate.minutes}`;
let productsInOrderHTML = '';
let totalAmount = 0;
for (let i = 0; i < selProductId.length; i++) {
await conn.promise().query(`UPDATE products
SET products.product_count_stock = products.product_count_stock - ${selProductId[i].count}
WHERE products.product_id = ${selProductId[i].product_id}`, err => {
if (err) {
throw err;
}
productsInOrderHTML += `<tr>
<td>
${selProductId[i].product_name}
</td>
<td>
${selProductId[i].count}
</td>
<td>
${selProductId[i].product_amount}
</td>
</tr>`;
totalAmount += selProductId[i].count *
selProductId[i].product_amount;
if (i === selProductId.length - 1) {
console.log('totalAmount: ' + totalAmount);
}
});
}
} else {
res.send('error');
}
});
} else {
res.send('error');
}
});