如何处理nodejs中的竞争条件



我正在尝试在MERN全栈应用程序上工作,其中前端发送api调用"/createDeckOfCards"到我的nodejs后端。目标是单击一个按钮来创建一副新的纸牌,然后返回创建的纸牌列表。参数nummofcards也会随这个调用一起发送。

在我的nodeJS后端,我有"/createDeckOfCards"端点,我使用。map()迭代创建每个卡,然后保存到mongoDB,如下所示:

const allCardsArray = [...Array(req.body.numOfCards).keys()]
allCardsArray.map(async (i)=>{
const eachCard = new eachCardModel({
eachCardTitle: String(i)
})

eachCard.save((err, doc) => {
if (err) return res.status(400).json({ errMsg: "Something went wrong" });
else{
CardDeckModel.findOneAndUpdate(
{_id: req.cardDeckCreated._id},
{$push:{allCards: doc}},
function(error, success){
if (error){
console.log(error)
return res.status(400).json({ errMsg: "Something went wrong" });
} else {
console.log("success")
}
}
)
}
});
})
console.log("COMPLETED") //DOES NOT EXECUTE LAST!
//THIS RETURNS BEFORE THE .map() is done
res.status(200).json({ 
createdCardDeckID: req.cardDeckCreated._id 
})
})

之后,我有第二个端点"/returnAllCardsInDeck"这里我像这样传入cardDeck的ID:

CardDeckModel.findOne({_id: req.body.createdCardDeckID}).populate({path: 'allCards', options: { sort: "eachCardTitle" } }).exec((err, cardDeck) => {
if (err) return res.status(400).json({ errMsg: "Something went wrong" });
else {
res.status(200).json({
CardDeck: cardDeck
})
}
})

问题是,CardDeck在allCardsArray.map()完成之前返回。这将是一个问题,因为我希望用户在牌组创建后看到牌组中的所有牌。但是因为&;/returnallcardsindeck &;在"/createDeckOfCards"之前执行,它返回一个未定义对象。

还有,我这样做对吗?特别是关于第一部分("/createDeckOfCards")。

试试这个,你不能用map做这样的异步调用。有一些模式可以解决这个问题。的承诺。都是其中之一。

const allCardsArray = [...Array(req.body.numOfCards).keys()]
await Promise.all(
allCardsArray.map((i)=>{
const eachCard = new eachCardModel({
eachCardTitle: String(i)
})
return eachCard.save()
.then(
() => 
CardDeckModel.findOneAndUpdate({_id: req.cardDeckCreated._id}, {$push:{allCards: doc}})
.then(() => console.log("success"))
.catch((error) => console.log(error) || res.status(400).json({ errMsg: "Something went wrong" });)
).catch(() => res.status(400).json({ errMsg: "Something went wrong" }))
})
)
console.log("COMPLETED") //DOES NOT EXECUTE LAST!
//THIS RETURNS BEFORE THE .map() is done
res.status(200).json({
createdCardDeckID: req.cardDeckCreated._id
})
})

您可以使用for ofasync/await代替map,像这样

const allCardsArray = [...Array(req.body.numOfCards).keys()];
for (let i of allCardsArray) {
const eachCard = new eachCardModel({
eachCardTitle: String(i),
});
try {
let doc = await eachCard.save();
await CardDeckModel.findOneAndUpdate(
{ _id: req.cardDeckCreated._id },
{ $push: { allCards: doc } }
);
} catch (error) {
return res.status(400).json({ errMsg: "Something went wrong" });
}
}
console.log("success");
res.status(200).json({
createdCardDeckID: req.cardDeckCreated._id,
});

相关内容

  • 没有找到相关文章