You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 22:48:01