Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The "this" object is empty in pre('save')

Tags:

mongoose

As I described in the title when I want to save a new mongoose document the pre('save') method fires, but the this element in it is an emtpty object.

The test snippet:

var schema = new mongoose.Schema({
    password:String
})

schema.pre('save',(next)=>{
    console.log(this)
    next()
})

var model = mongoose.model('Test',schema)

var test = new model({
    password:'testpass'
})

test.save()

I cant see the problem with this basic code.

I am using Mongoose v4.5.9.

like image 991
József Takó Avatar asked Aug 26 '16 12:08

József Takó


People also ask

What is pre save in Mongoose?

The save() function triggers validate() hooks, because mongoose has a built-in pre('save') hook that calls validate() . This means that all pre('validate') and post('validate') hooks get called before any pre('save') hooks.

How do I get the ObjectId after I save an object in Mongoose?

To get the object ID after an object is saved in Mongoose, we can get the value from the callback that's run after we call save . const { Schema } = require('mongoose') mongoose. connect('mongodb://localhost/lol', (err) => { if (err) { console. log(err) } }); const ChatSchema = new Schema({ name: String }); mongoose.

What is Mongoose types ObjectId?

Types. ObjectId . A SchemaType is just a configuration object for Mongoose. An instance of the mongoose. ObjectId SchemaType doesn't actually create MongoDB ObjectIds, it is just a configuration for a path in a schema.


2 Answers

The answer from user "unR" is correct. You can not use this when you are using an arrow function on a pre save function. You will also find this on all other types of mongoose schema functions. I have expanded on this answer to help clarify why this occurs.

This breaks:

schema.pre('save', (next) => { // arrow function
  console.log(this);
  next();
});

This works:

schema.pre('save', function preSave(next) { // regular function
  console.log(this);
  next();
});

The reason:

The problem occurs because of how arrow functions treat "scope" differently to regular functions. Arrow functions do not keep scope within the function but rather forcefully inherit scope from the outside or surrounding function (this means it will overwrite functions such as exampleMethod.bind(this)). In the case above; there is no outside function so the this value would be equal to undefined.

However, when you use the regular function declaration, the scope can be overwritten by mongoose using the .bind() method. As such, they bind the function to the schema object which allows you to have access to the schema properties and functions within the function.

Here is a helpful resource on arrow functions and how they work: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

like image 99
Jack Avatar answered Nov 02 '22 04:11

Jack


For whatever reason your function cannot have the es6 arrow syntax

schema.pre('save', function(next) {
    console.log(this)
    next()
})

Will work. I currently have no idea why.

like image 22
unR Avatar answered Nov 02 '22 03:11

unR