async problem array nodejs luwak kosong
saya ingin mendapatkan dari array ID yang datang di req.body nama dan harga masing-masing produk dan menyimpannya dalam model baru (pembayaran), untuk ini saya memeriksa setiap produk dan mencari id-nya di db (Product.findById) dan saya simpan sebagai objek di arrayProducts apa yang saya butuhkan (nama dan harga), tetapi pembayaran baru dibuat sebelum arrayProducts selesai diisi dan saya membuatnya kosong, karena saya dapat melakukannya sehingga pembayaran baru dibuat setelah forEach produk selesai?
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 });
}
});;
});
Jawaban
Anda perlu membaca tentang operasi non-pemblokiran dan asinkron di node.js. Anda Product.findById()adalah non-blocking dan asynchronous yang berarti callback-nya dipanggil LONG setelah seluruh route handler Anda selesai dijalankan dan tentunya setelah console.log(arrayProducts);dan semua kode yang muncul setelah itu.
Karena Anda ingin melakukan N permintaan dari database Anda dan Anda hanya ingin tahu kapan semuanya telah selesai, cara paling efisien untuk melakukannya adalah dengan menggunakan antarmuka Promise untuk database Anda, mengumpulkan berbagai janji dari semua operasi DB dan kemudian gunakan Promise.all()untuk memberi tahu saat semuanya selesai.
Inilah yang saya sarankan:
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 });
}
});
Hal lain yang hilang dari kode ini adalah:
- Memvalidasi nilai input
amount, clientId, products, services, officeIddan mengirimkan kesalahan yang sesuai jika ada yang hilang atau tidak valid. - Apa yang harus dilakukan jika produk yang ditentukan tidak ditemukan di database Anda?
- Kesalahan 404 mungkin tidak sesuai jika Anda mendapatkan kesalahan basis data (yang mungkin merupakan kesalahan 500).