代码之家  ›  专栏  ›  技术社区  ›  DevStarlight

蓝鸟创建新用户

  •  1
  • DevStarlight  · 技术社区  · 8 年前

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

    问题是,它创造了我 user 即使它启动了错误 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();
      }
    };
    

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

    谢谢你的建议。

    更新

    this 链接很有用。

    1 回复  |  直到 8 年前
        1
  •  2
  •   Community Marino Di Clemente    4 年前

    太长,读不下去了不要使用.catch()或.then(成功, )如果您不希望在发生错误后调用promise链中的后续函数。仅在链的末端捕获,以获得整个异步调用链的结果,而不会出现错误后不需要的调用。

    好的,让我们假设一个函数只返回一个被拒绝的承诺:

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

    会让那个控制台。日志“调用此日志…”以运行,因为错误正在处理中。输出将是:

    第二个参数,失败:禁止此操作

    调用此日志是因为在第二个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');
    });
    

    出现错误:错误:禁止此操作

    这在结束时调用,之前的“此日志被调用”日志未被触发,因为存在未处理的拒绝

    还有两个您可能需要处理的小问题:

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

    将打印错误堆栈跟踪,而不仅仅是控制台中的消息。