Can anyone figure out what's wrong with my code below?
From documentation it looks like the this
in Mongoose .pre('save')
method should be the model itself, but in my code below this
ends up being an empty object.
const Mongoose = require('./lib/database').Mongoose;
const Bcrypt = require('bcrypt');
const userSchema = new Mongoose.Schema({
email: { type: String, required: true, index: { unique: true } },
password: { type: String, required: true }
});
userSchema.pre('save', (next) => {
const user = this;
Bcrypt.genSalt((err, salt) => {
if (err) {
return next(err);
}
Bcrypt.hash(user.password, salt, (err, encrypted) => {
if (err) {
return next(err);
}
user.password = encrypted;
next();
});
});
});
const User = Mongoose.model('User', userSchema);
When saving a user, I get the following error [Error: data and salt arguments required]
.
function createUser(email, password, next) {
const user = new User({
email: email,
password: password
});
user.save((err) => {
if (err) {
return next(err);
}
return next(null, user);
});
}
createUser('[email protected]', 'testpassword', (err, user) => {
if (err) {
console.log(err);
}
else {
console.log(user);
}
process.exit();
});
If I remove the .pre('save')
then it saves fine of course. Version of Mongoose I'm using is 4.2.6.
Problem here is a fat arrow functions. You must rewrite your callback with simple functions. Here small example to show the diff
var obj = {};
obj.func1 = function () {
console.log(this === obj);
};
obj.func2 = () => {
console.log(this === obj);
};
obj.func1(); // true
obj.func1.bind(obj)(); // true
obj.func2(); // false
obj.func2.bind(obj)(); // false
I was able to figure out the issue. It turns out Arrow Functions in ES6 preserve the context of the declaring scope rather than using the context of the calling scope so changing the code to the below fixed the issue.
userSchema.pre('save', function (next) {
Bcrypt.genSalt((err, salt) => {
if (err) {
return next(err);
}
Bcrypt.hash(this.password, salt, (err, encrypted) => {
if (err) {
return next(err);
}
this.password = encrypted;
next();
});
});
});
Thank you Michelem for giving me the idea that ES6 may have been the culprit.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With