비동기 문제 배열 빈 nodejs 몽구스
Oct 19 2020
나는 req.body에 들어있는 ID 배열에서 각 제품의 이름과 가격을 얻고 새로운 모델 (결제)에 저장하고 싶습니다.이를 위해 각 제품을 살펴보고 ID를 찾습니다. db (Product.findById) 및 필요한 (이름 및 가격)을 arrayProducts에 개체로 저장하지만 arrayProducts가 채워지기 전에 newPayment가 생성되고 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 });
}
});;
});
답변
jfriend00 Oct 20 2020 at 03:12
node.js의 비 차단 비동기 작업에 대해 읽어야합니다. 귀하 Product.findById()는 비 블로킹 및 비동기식이므로 전체 경로 처리기가 실행을 마친 후 console.log(arrayProducts);그리고 그 이후에 오는 모든 코드 이후에 콜백이 LONG이라고 부릅니다 .
데이터베이스에서 N 개의 요청을하고 싶고 모든 요청이 언제 완료되었는지 알고 싶기 때문에 가장 효율적인 방법은 데이터베이스에 Promise 인터페이스를 사용하고 모든 DB 작업에서 일련의 promise를 수집하는 것입니다. 그런 다음 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하고 누락되거나 유효하지 않은 경우 적절한 오류를 보냅니다. - 데이터베이스에없는 제품이 지정된 경우 어떻게해야합니까?
- 데이터베이스 오류 (아마 500 오류 일 수 있음)가 발생하는 경우 404 오류가 적절하지 않을 수 있습니다.