如何解决如何处理 nodejs 中的竞争条件
我正在尝试开发一个 MERN 全栈应用程序,其中前端向我的 nodejs 后端发送对“/createDeckOfCards”的 api 调用。目标是点击一个按钮来创建一副新的纸牌,然后返回创建的纸牌列表。 参数 numOfCards 也与此调用一起发送。
所以在我的 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”)。
解决方法
试试这个,你不能用地图做这样的异步调用。有一些模式可以解决这个问题。 Promise.all 就是其中之一。
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 of
和 async/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,});
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。