javascript - 如何处理nodejs中的竞争条件

标签 javascript node.js mongoose race-condition mern

我正在尝试开发一个 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”之前执行,所以它返回的是一个 undefined object 。
另外,我这样做对吗?特别是关于第一部分(“/createDeckOfCards”)。

最佳答案

试试这个,你不能用 map 做这样的异步调用。有一些模式可以解决这个问题。 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
    })
})

关于javascript - 如何处理nodejs中的竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66173267/

相关文章:

javascript - 如何在javascript中打印字符串数组?

javascript - 扫描特定 html 元素的页面并分配 css 类

mongodb - 在一个集合的所有文档中具有唯一值的数组

Node.js mongoose 更新文档

mysql - 最适合我的应用程序类型的数据库? MySQL? MongoDB? PostgreSQL?沙发数据库?

javascript - 如何查找除了两小时前更新的文档之外的文档?

javascript - Google Chrome 是否支持 toJSON?

JavaScript 函数将日期字符串参数更改为一系列数字

node.js - Nodejs Express hbs : css MIMETYPE turns into text/html

javascript - IBM Bluemix Node.js 原生 Promise 支持