【问题标题】:Mongoose middleware schema.pre('save', ...)Mongoose 中间件 schema.pre('save', ...)
【发布时间】:2021-03-28 17:57:01
【问题描述】:

我正在使用 Mongoose 驱动程序在 NodeJS 中创建一个 REST API。我想在保存密码之前对密码进行哈希处理。同样,我使用的是 Mongoose Schema,我在其中为我的用户模型创建了一个 userSchema。对于散列,我使用了以下函数。

userSchema.pre('save', async (next) => {
    const user = this;
    console.log(user);
    console.log(user.isModified);
    console.log(user.isModified());
    console.log(user.isModified('password'));
    if (!user.isModified('password')) return next();
    console.log('just before saving...');
    user.password = await bcrypt.hash(user.password, 8);
    console.log('just before saving...');
    next();
});

但在创建用户或修改用户时,我收到错误 500,并且返回 {}。我的路由器如下。

router.post('/users', async (req, res) => {
    const user = User(req.body);
    try {
        await user.save();
        res.status(201).send(user);
    } catch (e) {
        res.status(400).send(e);
    }
});

router.patch('/users/:id', async (req, res) => {
    const updateProperties = Object.keys(req.body);
    const allowedUpdateProperties = [
        'name', 'age', 'email', 'password'
    ]; 
    const isValid = updateProperties.every((property) => allowedUpdateProperties.includes(property));
    if (!isValid) {
        return res.status(400).send({error: "Invalid properties to update."})
    }

    const _id = req.params.id;
    try { 
        const user = await User.findById(req.params.id);
        updateProperties.forEach((property) => user[property] = req.body[property]);
        await user.save();
        if (!user) {
            return res.status(404).send();
        }
        res.status(200).send(user);
    } catch (e) {
        res.status(400).send(e);
    }
});

以下是我的控制台输出。

Server running on port 3000
{}
undefined

注释掉 userSchema.pre('save', ...) 一切都按预期工作。请你能帮我弄清楚我哪里出错了。

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    使用函数定义而不是mongoose的箭头函数pre保存中间件:

    userSchema.pre('save', async function(next) { // this line
        const user = this;
        console.log(user);
        console.log(user.isModified);
        console.log(user.isModified());
        console.log(user.isModified('password'));
        if (!user.isModified('password')) return next();
        console.log('just before saving...');
        user.password = await bcrypt.hash(user.password, 8);
        console.log('just before saving...');
        next();
    });
    

    更新:

    区别在于this上下文,如果你在const user = this;这一行中使用arrow函数,这就是你当前的文件(我猜是模式文件)。

    当您使用function 关键字时,this 上下文将属于调用者对象(用户实例)。

    【讨论】:

    • 谢谢。它正在工作。你能解释一下使用 function 关键字而不是箭头符号有什么区别吗?
    • @hoangdy ,你能不能也把它的异步/同步版本。
    • @Becauseihatemyself 你是什么意思?
    • 我的意思是异步/等待风格的回答。 bcrypt,在异步等待中为哈希生成盐。
    • @Becauseihatemyself 只需调用hashSync 而不是hash 并删除asyncawait。但是,async 方式是bcrypt 推荐的。
    猜你喜欢
    • 2021-01-09
    • 2016-06-27
    • 2021-06-03
    • 2018-12-19
    • 2017-01-31
    • 2014-09-18
    • 2018-03-31
    • 1970-01-01
    • 2019-01-31
    相关资源
    最近更新 更多