2016-10-15 61 views
1

我是Bluebird的新手,我试图创建一个新用户,但reject函数无法按预期工作。蓝鸟创建新用户

问题是它创建了我,即使它启动了错误There nickname is already in use

以下是我粘贴我的代码。

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 }); 
    }); 
}); 

在咨询感谢。

UPDATE

只是为了澄清大家,与承诺开始,并正在寻找最佳的做法,我想this链接是有帮助的。

+1

您应该避免['Promise' constructor antipattern](http://stackoverflow.com/q/23803743/1048572)。看看[通过ES6 Promises](http://stackoverflow.com/q/35856041/1048572) – Bergi

+0

是你使用的创建一个'new promise'的小技巧,它包含验证和一个'猫鼬'承诺?我是否应该像验证一样用Promise.reject(new Error('Whatever error'))'将其分开,并返回'mongoose'诺言? – DevStarlight

+1

是的,确切地说。如果你不想返回一个猫鼬的诺言,但你可以使用'return Promise.resolve(... .findOne(...).exec())。然后(...)' – Bergi

回答

2

TLDR;如果您不想在发生错误后调用承诺链中的后续函数,则不要使用.catch()或.then(成功,错误)捕获错误。只捕获链的末尾,以获得整个异步调用链的结果,而不会在错误发生后发生意外调用。

好吧,让我们想象,只是返回一个拒绝承诺的功能:

function fakeForbiddenAsyncOperation(){ 
    return new Promise(function(resolve , reject){ 
     return reject('This operation is forbidden'); 
    }); 
} 

然后,无极链,如:

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“该日志被调用。 ..'来运行,因为错误正在处理中。输出将是:

second parameter, failure: This operation is forbidden

This log is called, because the previous error was catched in the second 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'); 
}); 

哪个输出是:

There was an err: Error: This operation is forbidden

this is called at the end, and the previous "this log is called" log wasnt fired because there was an unhandled rejection

所以,“第一个参数,成功”日志将永远不会触发(因此,一个User.create()函数,或者你不想执行,如果有一个以前的错误任何其他操作,也不会)。

也有2个次要问题,你也许要处理:

Bluebird documentation建议使用.catch()代替。然后(成功,失败):

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')); 

将打印错误堆栈跟踪,而不是在控制台只是一个消息。

+0

我以回调的方式使用承诺错误的方式。现在我懂了。谢谢! – DevStarlight