猫鼬模型中的预钩子为ES6类

时间:2018-07-07 15:48:51

标签: node.js mongodb mongoose

我已经定义了猫鼬模式和类,但是在pre validate钩子中,this上下文为空。我得到TypeError: this.validateColor is not a function

bike.js

const mongoose = require('mongoose');

const Schema = mongoose.Schema;

// Mongodb Object Model
// =============================================================================
let BikeSchema = new Schema({
    color: {
        type: String,
        required: true
    },
    wheels: {
        type: Number,
        required: true
    }
});

// Bike Class
// =============================================================================
class BikeClass {

    validateColor() {
        if(this.color !== 'blue' && this.color != 'red') {
            this.invalidate('Not a valid color');
        }
    }

    validateWheels() {
        if(this.wheels < 2 || this.wheels > 3) {
            this.invalidate('Not a valid number of wheels');
        }
    }
}

BikeSchema.loadClass(BikeClass);

// Do validation checks as API hooks
BikeSchema.pre('validate', next => {
    // Problem: this = {}
    this.validateColor();
    this.validateWheels();
    next();
});

module.exports = mongoose.model('Bike', BikeSchema);

index.js

const Bike = require('./bike.js');
const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/bikes');
const db = mongoose.connection;

// Connect to Mongo db
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function () {
    console.debug('Connected to mongo successfully');
    let bike = new Bike();
    bike.color = 'red';
    bike.wheels = 1;
    bike.save()
    .catch(err => {
        console.error(err);
    })
});

1 个答案:

答案 0 :(得分:1)

如果要在Mongoose钩子中的某个位置引用this,则不能在Mongoose钩子中使用箭头函数,因为箭头函数处理this的方式与老式函数表达式不同。

From MDN箭头函数表达式的语法比函数表达式短,并且没有自己的this,arguments,super或new.target。这些函数表达式最适合非方法函数,因此不能用作构造函数。

我记得在Mongoose文档中的某个地方读到,钩子只能具有老式的函数表达式,但是我在任何地方都找不到。

无论如何,只需将您的钩子重写为类似的内容

BikeSchema.pre('validate', function (next) {
  // Problem: this = {}
  this.validateColor();
  this.validateWheels();
  next();
});

请注意,由于可能的错误问题,应将命名函数用作挂钩函数,因此明天引发错误时,您将确切知道代码在哪个挂钩函数中失败。