I'm new to Bluebird
and I'm trying to create a new User but the reject
function doesn't work as expected.
The problem is that it creates me the user
even though it launches the error There nickname is already in use
.
Here bellow I paste my code.
User.js
var User = require('../models/user');
var Promise = require('bluebird');
module.exports = {
validateFields: function (nickname) {
return new Promise(function (response, reject) {
if (!nickname) {
reject('You must provide the nickname');
} else if (nickname.length < 4 || nickname.length > 20) {
reject('The nickname must be longer than 4 and shorter than 20 characters');
} else {
nickname = nickname.trim();
User.findOne({ "nickname": nickname }).exec()
.then(function (user) {
if (user) {
reject('There nickname is already in use');
} else {
response();
}
}, function (err) {
reject('There is an error trying to verify the nickname');
});
}
});
},
registerUser: function (user_id, nickname) {
return new User({ user_id: user_id, nickname: nickname }).save();
}
};
register.js
var validator = require('validator');
var Promise = require('bluebird');
var Account = require('../../models/account');
module.exports = {
validateFields: function (email, password) {
return new Promise(function (response, reject) {
if (!email) {
reject('You must provide the email');
} else if (!password) {
reject('You must provide the password');
} else if (email.length < 6) {
reject('The email is too short');
} else if (email.length > 40) {
reject('The email is too long');
} else if (!validator.isEmail(email)) {
reject('The email is not valid');
} else {
Account.findOne({ email: email }).exec()
.then(function (account) {
if (account) {
reject('There is already an email');
} else {
console.log(account);
response();
}
}, function (err) {
reject('There is an error trying to verify the email');
});
}
});
},
registerAccount: function (email, password) {
return new Account({ email: email, password: password }).save();
}
};
routes.js
var Promise = require('bluebird');
var user = require('./routes/user');
var account = require('./routes/auth/register');
router.post('/register', function (req, res, next) {
account.validateFields(req.body.email, req.body.password)
.then(function () {
return user.validateFields(req.body.nickname);
}, function (err) {
return res.status(400).json({ msg: err });
})
.then(function () {
req.body.email = req.body.email.trim();
req.body.password = req.body.password.trim();
console.log('bien');
return account.registerAccount(req.body.email, req.body.password);
}, function (err) {
console.log('mal');
return res.status(400).json({ msg: 'There was an error trying to save the email' });
})
.then(function (data) {
return user.registerUser(data, req.body.nickname);
}, function (err) {
return res.status(400).json({ msg: 'There was an error trying to save the user' });
})
.then(function () {
return res.status(200);
}, function (err) {
console.log(err);
return res.status(400).json({ msg: err });
})
.catch(function (err) {
console.log('catch');
return res.status(400).json({ msg: err });
});
});
Thanks in advice.
UPDATE
Just to clarify everybody that start with promises and is looking for best practices, I guess this link is helpful.
答案 0 :(得分:2)
TLDR;如果您不希望在发生错误后调用promise链中的后续函数,请不要使用.catch()或.then(成功,错误)来捕获错误。仅在链的末尾捕获以获取整个异步调用链的结果,而不会在出错后进行不需要的调用。
好吧,让我们设想一个只返回被拒绝的承诺的函数:
function fakeForbiddenAsyncOperation(){
return new Promise(function(resolve , reject){
return reject('This operation is forbidden');
});
}
然后,Promise链如:
fakeForbiddenAsyncOperation().then(
function(){
console.log('first parameter, success');
},
function(err ){
console.log('second parameter, failure: ' + err);
})
.then(function(){
console.log('This log is called, because the previous error was catched in the second then() lambda');
})
.catch(console.log);
将调用此console.log&#39;此日志...&#39;运行,因为正在处理错误。输出将是:
第二个参数,失败:此操作被禁止
调用此日志,因为先前的错误是在第二个then()lambda
中捕获的
您希望在代码中执行的操作,如果验证中存在先前错误,则阻止创建用户,更像是:
fakeForbiddenAsyncOperation().then(
function(){
console.log('first parameter, success');
})
.then(function(){
console.log('This log is called');
} , function(err){
console.log('There was an err: ' + err);
console.log('this is called at the end, and the previous "this log is called" log wasn\'t fired because there was an unhandled rejection');
});
哪个输出是:
有一个错误:错误:此操作被禁止
这在最后被调用,而前一个&#34;这个日志被称为&#34;日志没有被解雇,因为有一个未处理的拒绝
所以&#39;第一个参数,成功&#39; log永远不会触发(因此,User.create()函数,或者如果出现上一个错误,您不想执行的任何其他操作也不会触发)。
您可能还想处理两个小问题:
Bluebird documentation建议使用.catch()代替.then(成功,失败):
forbiddenAsyncOperation().then(
function(){
console.log('first parameter, success');
})
.then(function(){
console.log('This log is called');
})
.catch(function(){
console.log('this is called at the end, and the previous "this log is called" log wasn\'t fired because there was an unhandled rejection');
});
表现得像上一个例子。
另外,is better to reject errors instead of strings:
reject(new Error('The nickname must be longer than 4 and shorter than 20 characters'));
将打印错误堆栈跟踪,而不仅仅是控制台中的消息。