Node.js使用Mongoose如何在保存到MongoDB前修改字段值
问题分析
- 异步逻辑未等待完成就提前放行保存流程:
pre('save')钩子中的axios.get是异步网络请求,你没有等待请求返回结果就直接调用了next(),此时totalCost的赋值逻辑还未执行,数据就已经进入入库流程,最终存储的是默认值0。 - 缺少异步错误捕获逻辑:如果axios请求超时或失败,没有对应的错误处理机制,既无法排查问题,也不会终止错误的保存操作。
- 冗余传值干扰:你在新建Reservation实例时传入了
req.body.totalCost,该值最终会被计算逻辑覆盖,属于冗余字段,还可能出现前端传值干扰计算结果的问题。
修复方案
1. 重写pre save钩子为异步写法
将钩子回调改为async函数,用await等待axios请求完成,所有赋值逻辑执行完再调用next(),同时增加错误捕获:
reservationSchema.pre('save', async function(next){ try { const date1 = new Date(this.checkIn); const date2 = new Date(this.checkOut); const diff = Math.abs(date1.getTime() - date2.getTime()); const diffDays = Math.ceil(diff / (1000 * 3600 * 24)); // 等待房间接口返回结果后再计算费用 const roomRes = await axios.get(`http://localhost:5555/rooms/${this.roomID}`); const roomCost = roomRes.data.cost; this.totalCost = (this.numberOfAdults + this.numberOfChildren) * roomCost * diffDays; // 所有逻辑执行完成再放行保存流程 next(); } catch (err) { // 出现错误时终止保存,返回错误信息 next(err); } })
2. 优化post接口参数
删掉冗余的totalCost传值:
router.post('/', async(req, res) => { const reservation = new Reservation({ guestID: mongoose.Types.ObjectId(req.body.guestID), roomID: mongoose.Types.ObjectId(req.body.roomID), checkIn: req.body.checkIn, checkOut: req.body.checkOut, numberOfAdults: req.body.numberOfAdults, numberOfChildren: req.body.numberOfChildren // 移除totalCost传值,由钩子自动计算 }) try { const reservationRecord = await reservation.save() res.json(reservationRecord) } catch(err) { console.log(err) res.status(400).send("Error") } })
内容的提问来源于stack exchange,提问作者474gaurav
相关产品推荐
相关产品推荐

