函数未定义,Bookshelf.js 模型函数未被识别为函数
Function is undefined, Bookshelf.js model function is not being recognized as a function
我正在使用 Bookshelf.js
处理用户注册 API 端点,使用 NodeJS 和 ExpressJS 设计。但是在 POST 访问寄存器 url 后,我一直在其中一个用户模型函数中遇到错误。
这里是routes/index.js
var User = require(./models/User);
router.post('/register', function(req, res, next){
if(!req.body.username || !req.body.password){
return res.status(400).json({message: 'Please fill out all fields'});
}
try {
var hash = User.createPassword(req.body.password);
console.log(hash);
new User({email: req.body.username, name: req.body.username, password: hash}).save().then(function(model) {
return res.json({token: this.generateJWT()});
});
} catch (ex) {console.log(ex.stack);}
});
这里是models/Users.js
var jwt = require('jsonwebtoken');
var bcrypt = require('bcrypt');
var bookshelf = require('../config/bookshelf');
var User = bookshelf.Model.extend({
tableName: 'users',
constructor: function() {
bookshelf.Model.apply(this, arguments);
this.on('saving', function(model, attrs, options) {
console.log(this.createPassword(model.attributes.password));
});
},
createPassword: function(password) {
bcrypt.genSalt(10, function (err, salt) {
if(err) return next(err);
bcrypt.hash(password, salt, function (err, hash) {
if(err) return next(err);
return hash;
});
});
},
validPassword: function(password, encryptedPass) {
bcrypt.compare(password, user.encryptedPass, function (err, match) {
if(err) cb(err);
return (match) ? true : false;
});
},
generateJWT: function() {
// set expiration to 60 days
var today = new Date();
var exp = new Date(today);
exp.setDate(today.getDate() + 60);
return jwt.sign({
_id: this._id,
email: this.email,
exp: parseInt(exp.getTime() / 1000),
}, 'SECRET');
}
});
module.exports = User;
当我尝试 POST 注册时,我得到以下堆栈跟踪:
TypeError: undefined is not a function
at \routes\index.js:185:21
at Layer.handle [as handle_request] (\node_modules\express\lib\router\layer.js:95:5)
at next (\node_modules\express\lib\router\route.js:131:13)
at Route.dispatch (\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (\node_modules\express\lib\router\layer.js:95:5)
...
在堆栈跟踪中,\routes\index.js:185:21 是以下行:var hash = User.createPassword(req.body.password);
at createPassword
.
那么我做错了什么?为什么无法识别 createPassword
函数?
User
是构造函数,但该方法是在其原型上定义的。您必须创建一个实例来调用方法。尝试
var user = new User({email: req.body.username, name: req.body.username, password: hash});
var pwd = user.createPassword();
user.save()
请注意,从您的方法的外观来看,它作为静态方法可能更好(它不访问 this),另一个答案描述了如何创建。
createPassword()
未定义为静态方法(a.k.a。classProperties
),但您是这样调用它的。试试这个模型定义。它应该直接在用户 class 上公开 createPassword()
作为 static method.
var User = bookshelf.Model.extend({ //instance methods
tableName: 'users',
constructor: function() {
bookshelf.Model.apply(this, arguments);
// ...
},
validPassword: function(password, encryptedPass) {
// ...
},
generateJWT: function() {
// ...
}
}, { //static methods
createPassword: function(password) {
// ...
}
});
额外:您需要修复您的 createPassword,因为它是异步的。下面我将它转换为 Promise 返回函数(因为 bookshelf 广泛使用 promises)并展示了路由处理程序的示例用法
createPassword: function () {
return new Promise(function (resolve, reject) {
bcrypt.genSalt(10, function (err, salt) {
if (err) return reject(err);
bcrypt.hash(password, salt, function (err, hash) {
if (err) return reject(err);
resolve(hash);
});
});
});
}
// in route handler
if (!req.body.username || !req.body.password) {
return res.status(400).json({
message: 'Please fill out all fields'
});
}
try {
User.createPassword(req.body.password)
.then(function(hash) {
console.log(hash);
return new User({
email: req.body.username,
name: req.body.username,
password: hash
}).save();
}).then(function (model) {
return res.json({
token: this.generateJWT()
});
}).catch(function(ex) {
console.log(ex.stack);
});
} catch (ex) {
console.log(ex.stack);
}
我正在使用 Bookshelf.js
处理用户注册 API 端点,使用 NodeJS 和 ExpressJS 设计。但是在 POST 访问寄存器 url 后,我一直在其中一个用户模型函数中遇到错误。
这里是routes/index.js
var User = require(./models/User);
router.post('/register', function(req, res, next){
if(!req.body.username || !req.body.password){
return res.status(400).json({message: 'Please fill out all fields'});
}
try {
var hash = User.createPassword(req.body.password);
console.log(hash);
new User({email: req.body.username, name: req.body.username, password: hash}).save().then(function(model) {
return res.json({token: this.generateJWT()});
});
} catch (ex) {console.log(ex.stack);}
});
这里是models/Users.js
var jwt = require('jsonwebtoken');
var bcrypt = require('bcrypt');
var bookshelf = require('../config/bookshelf');
var User = bookshelf.Model.extend({
tableName: 'users',
constructor: function() {
bookshelf.Model.apply(this, arguments);
this.on('saving', function(model, attrs, options) {
console.log(this.createPassword(model.attributes.password));
});
},
createPassword: function(password) {
bcrypt.genSalt(10, function (err, salt) {
if(err) return next(err);
bcrypt.hash(password, salt, function (err, hash) {
if(err) return next(err);
return hash;
});
});
},
validPassword: function(password, encryptedPass) {
bcrypt.compare(password, user.encryptedPass, function (err, match) {
if(err) cb(err);
return (match) ? true : false;
});
},
generateJWT: function() {
// set expiration to 60 days
var today = new Date();
var exp = new Date(today);
exp.setDate(today.getDate() + 60);
return jwt.sign({
_id: this._id,
email: this.email,
exp: parseInt(exp.getTime() / 1000),
}, 'SECRET');
}
});
module.exports = User;
当我尝试 POST 注册时,我得到以下堆栈跟踪:
TypeError: undefined is not a function
at \routes\index.js:185:21
at Layer.handle [as handle_request] (\node_modules\express\lib\router\layer.js:95:5)
at next (\node_modules\express\lib\router\route.js:131:13)
at Route.dispatch (\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (\node_modules\express\lib\router\layer.js:95:5)
...
在堆栈跟踪中,\routes\index.js:185:21 是以下行:var hash = User.createPassword(req.body.password);
at createPassword
.
那么我做错了什么?为什么无法识别 createPassword
函数?
User
是构造函数,但该方法是在其原型上定义的。您必须创建一个实例来调用方法。尝试
var user = new User({email: req.body.username, name: req.body.username, password: hash});
var pwd = user.createPassword();
user.save()
请注意,从您的方法的外观来看,它作为静态方法可能更好(它不访问 this),另一个答案描述了如何创建。
createPassword()
未定义为静态方法(a.k.a。classProperties
),但您是这样调用它的。试试这个模型定义。它应该直接在用户 class 上公开 createPassword()
作为 static method.
var User = bookshelf.Model.extend({ //instance methods
tableName: 'users',
constructor: function() {
bookshelf.Model.apply(this, arguments);
// ...
},
validPassword: function(password, encryptedPass) {
// ...
},
generateJWT: function() {
// ...
}
}, { //static methods
createPassword: function(password) {
// ...
}
});
额外:您需要修复您的 createPassword,因为它是异步的。下面我将它转换为 Promise 返回函数(因为 bookshelf 广泛使用 promises)并展示了路由处理程序的示例用法
createPassword: function () {
return new Promise(function (resolve, reject) {
bcrypt.genSalt(10, function (err, salt) {
if (err) return reject(err);
bcrypt.hash(password, salt, function (err, hash) {
if (err) return reject(err);
resolve(hash);
});
});
});
}
// in route handler
if (!req.body.username || !req.body.password) {
return res.status(400).json({
message: 'Please fill out all fields'
});
}
try {
User.createPassword(req.body.password)
.then(function(hash) {
console.log(hash);
return new User({
email: req.body.username,
name: req.body.username,
password: hash
}).save();
}).then(function (model) {
return res.json({
token: this.generateJWT()
});
}).catch(function(ex) {
console.log(ex.stack);
});
} catch (ex) {
console.log(ex.stack);
}