ปัญหา async อาร์เรย์ว่าง nodejs พังพอน
ฉันต้องการได้รับจากอาร์เรย์ของ ID ที่มาใน req ใครคือชื่อและราคาของแต่ละผลิตภัณฑ์และบันทึกในรูปแบบใหม่ (การชำระเงิน) สำหรับสิ่งนี้ฉันอ่านแต่ละผลิตภัณฑ์และค้นหา ID ใน db (Product.findById) และฉันบันทึกเป็นอ็อบเจ็กต์ใน arrayProducts สิ่งที่ฉันต้องการ (ชื่อและราคา) แต่ newPayment ถูกสร้างขึ้นก่อนที่ arrayProducts จะเติมเสร็จและฉันสร้างมันว่างเปล่าอย่างที่ฉันทำได้เพื่อสร้าง newPayment หลังจากสำหรับแต่ละผลิตภัณฑ์เสร็จสิ้น?
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()ไม่ใช่การปิดกั้นและแบบอะซิงโครนัสซึ่งหมายความว่าการเรียกกลับเรียกว่า LONG หลังจากที่ตัวจัดการเส้นทางทั้งหมดของคุณดำเนินการเสร็จสิ้นและแน่นอนว่าหลังจากconsole.log(arrayProducts);และรหัสทั้งหมดที่มาหลังจากนั้น
เนื่องจากคุณต้องการทำ N คำขอจากฐานข้อมูลของคุณและคุณแค่อยากรู้ว่าเมื่อใดเสร็จสิ้นวิธีที่มีประสิทธิภาพที่สุดในการทำเช่นนั้นคือการใช้อินเตอร์เฟส Promise สำหรับฐานข้อมูลของคุณรวบรวมอาร์เรย์ของคำสัญญาจากการดำเนินการ DB ทั้งหมด แล้วใช้Promise.all()เพื่อแจ้งเมื่อเสร็จสิ้น
นี่คือสิ่งที่ฉันจะแนะนำ:
router.post('/new/payment', async (req, res) => {
const date = Date.now();
const { amount, clientId, products, services, officeId } = req.body;
try {
const allProducts = await Promise.all(products.map(async (product) => {
const item = await Product.findById(product);
return {name: item.name, price: item.price};
}));
const newPayment = new Payment({ amount, clientId, products: allProducts, services, officeId, date });
await newPayment.save();
res.status(201).send({ status: "Payment successful", id: newPayment._id });
} catch(err) {
res.status(404).send({ error: "Oh uh, something went wrong", err: err });
}
});
สิ่งอื่น ๆ ที่ขาดหายไปจากรหัสนี้ ได้แก่ :
- ตรวจสอบความถูกต้องของค่าอินพุตสำหรับ
amount, clientId, products, services, officeIdและส่งข้อผิดพลาดที่เหมาะสมหากมีค่าใดหายไปหรือไม่ถูกต้อง - จะทำอย่างไรหากระบุผลิตภัณฑ์ที่ไม่พบในฐานข้อมูลของคุณ?
- ข้อผิดพลาด 404 อาจไม่เหมาะสมหากคุณได้รับข้อผิดพลาดฐานข้อมูล (ซึ่งอาจเป็นข้อผิดพลาด 500)