Mongoose 中间件 schema.pre('保存', ...)

imh*_*gga 2 mongoose mongodb node.js

我正在使用 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();
});
Run Code Online (Sandbox Code Playgroud)

但在创建用户或修改用户时,我收到错误 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);
    }
});
Run Code Online (Sandbox Code Playgroud)

以下是我的控制台输出。

Server running on port 3000
{}
undefined
Run Code Online (Sandbox Code Playgroud)

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

hoa*_*gdv 8

对于 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();
});
Run Code Online (Sandbox Code Playgroud)

更新:

区别在于上下文,如果您在这一行中this使用函数,那么现在这就是您当前的文件(我猜是架构文件)。arrowconst user = this;

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