Схема промежуточного программного обеспечения Mongoose.pre(‘сохранить’, …)

#node.js #mongodb #mongoose

#node.js #mongodb #мангуст

Вопрос:

Я создаю REST API в NodeJS, используя драйвер Mongoose. Я хочу хэшировать пароли перед их сохранением. Для того же я использую схему Mongoose, где я создал пользовательскую схему для своей пользовательской модели. А для хеширования я использовал следующую функцию.

 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’, …) все работает так, как ожидалось. Пожалуйста, не могли бы вы помочь мне понять, где я ошибаюсь.

Ответ №1:

Использование определения функции вместо функции стрелки для pre промежуточного программного обеспечения mongoose save:

 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 в контексте, если вы используете arrow функцию в этой строке const user = this; , теперь это ваш текущий файл (файл схемы, я полагаю).

При использовании function ключевого this слова контекст будет принадлежать вызывающему объекту (экземпляру пользователя).

Комментарии:

1. Спасибо. Это работает. Не могли бы вы объяснить, какая разница при использовании ключевого слова function, а не символа стрелки?

2. @hoangdy, можете ли вы также установить его асинхронную / синхронизирующую версию.

3. @Becauseihatemyself что вы имеете в виду?

4. Я имею в виду ответ в стиле async / await. bcrypt, генерирующий соль для хеширования в асинхронном ожидании.

5. @Becauseihatemyself Просто вызовите hashSync вместо hash и удалите async , await . Но, async способ рекомендуется bcrypt .