Пара проблем с кодом здесь, но насколько я могу понять, что вы действительно хотите сделать, это:
// note that "async" is here because inner methods use "await"
router.post("/item/:id", middleware.isLoggedIn, async (req, res) => {
try {
let item = await Item.findById(req.params.id);
// Do casting manually because you really want to
let soldPrice = parseFloat(req.body.soldPrice);
let soldQuantity = parseInt(req.body.soldQuantity);
let soldItem = {
id: item._id,
item: item.name,
askPrice: item.price
};
// create the sold item
let soldItem = await SoldItem.create({
soldItem,
soldPrice,
soldQuantity
});
// update the item
await item.update({ "$inc": { "quantity": (soldQuantity * -1) } });
// Then respond
req.flash("success", "Item Sold");
res.redirect("/products");
} catch(e) {
console.log("err", err.stack);
// really should send the error on res here as well
}
})
Или, если у вас на самом деле нет поддержки async/await
в вашей версии узла, то с простыми обещаниями:
router.post("/item/:id", middleware.isLoggedIn, (req, res) => {
// Do casting manually because you really want to
let soldPrice = parseFloat(req.body.soldPrice);
let soldQuantity = parseInt(req.body.soldQuantity);
Item.findById(req.params.id).then(item =>
SoldItem.create({
soldItem: {
id: item._id,
item: item.name,
askPrice: item.price
},
soldPrice,
soldQuantity
})
.then(() => item.update({ "$inc": { "quantity": (soldQuantity * -1) }));
}).then(() => {
// Then respond
req.flash("success", "Item Sold");
res.redirect("/products");
})
.catch(e => {
console.log("err", err.stack);
// really should send the error on res here as well
});
})
Таким образом, две «основные» проблемы в коде заключаются в том, что значение в req.body.soldQuantity
на самом деле является «строкой». Когда вы отправляете такие значения через что-то вроде SoldItem.create()
, тогда mongoose использует «схему» для приведения значений во все, что определено в схеме. В вашем случае это будет Number
.
JavaScript примет «разумное предположение» с более поздним оператором soldQuantity *-1
и «cast» для вас, но на самом деле вы должны знать о таких вещах и просто делать преобразование типов в коде «явно», а не полагаться на неявное приведение.
Следующей проблемой был вызов update()
. У мангусты есть «две формы»: Model.update()
и Document.update()
. Первый применяет условие «запрос», как в:
await Model.update({ "_id": 1 },{ "$inc": { "rounds": 1 } })`
Версия Document
или «экземпляр» работает с «уже извлеченным» документом и имеет другой синтаксис:
let document = await Model.findById(1);
await document.update({ "$inc": { "rounds": 1 } });
Так как вы уже сделали Item.findById()
, то возвращенный «документ» используется для этой формы update()
способом, который в основном «подразумевает»:
await Item.update(
{ "_id": item._id }, // this is implied from the "instance"
{ "$inc": { "quantity": (soldQuantity * -1) } }
);
Но, конечно, написано в «более короткой» форме «без запроса», как показано в коде.
Остальное действительно сводится к неправильному пониманию сочетания Обещаний и обработки «обратного вызова» и цели ключевых слов async/await
и того, как они переводятся в стандартную обработку обещаний. Но приведенный код должен исправить эти заблуждения, теперь у вас есть пример для подражания.