使用被拒绝的promise来处理错误的HTTP调用?

时间:2017-03-08 19:03:38

标签: node.js express mongoose

所以,我有以下代码:

function SignUp(req, res, next){

    const userCreds = {
        email: req.body.email,
        password: req.body.password
    }

    //Username and password must exist
    if(!userCreds.email || !userCreds.password){
        res.status(422).send({ error: 'Email and Password required'});
        throw new Error(('Email and Password Required'));
    }

    //See if email is already being used
    Users.findOne({ email: userCreds.email })
    .then(function(user){
        //If user does exist, return Error
        if(user){
            res.status(422).send({ error: 'Email is in use'});
            throw new Error(('Email and Password Required'));
        }

        //Else if email is true, create and save user error
        const newUser = new Users(userCreds);

        //Save the user
        return newUser.save(); //Return promise
    })
    .then(function(doc){
        //Respond saying all OK
        res.json({
            success: true,
            email: doc.email
        });
    })
    .catch(function(err){
        if(err)
            return next(err);
    });
}

上面的函数传递给Express路由,就像这样 app.get('/signup', SignUp);

在此代码中,有两个不同的错误'可能会发生,我需要处理。一种错误是无法处理用户请求(尝试创建帐户而不提供电子邮件和密码,或使用已经使用的电子邮件)。第二种错误是我无法控制的错误:来自Mongoose包的被拒绝的承诺。

让我们说我收到了一个错误的请求,类型1的错误。我想通过将响应的标头设置为422来处理它,并发送一条消息,详细说明为什么它不能被处理。此时执行将结束。

如果我收到类型2的错误,我想调用next(error)并在此时停止执行。

问题是,通过链接.then()函数,我无法从代码块中return而无法跳转到以下.next()

解决此问题的一种方法是,当我收到类型1或2的错误时,通过throw new Error()抛出错误,并在.catch()处理案例,但我不确定这将是一种好的或坏的做法。

我怎样才能使{I} {{}}}块中的错误处理然后停止执行?那会是最好的方法吗?

有没有更好的方法来处理Express中的这种情况?我错过了什么吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

解决方案是创建一个Error子类(例如,使用error-subclass)并抛出这些子实例,以防您想要发出处理错误信号。

随后,在.catch()处理程序中,您检查错误是否是该自定义错误类的实例,如果是,则返回422响应。如果没有,请将其传递给next

const ErrorSubclass = require('error-subclass').default;

class ProcessingError extends ErrorSubclass {}

Users.findOne({ email: userCreds.email })
.then(function(user){
    if (user) {
      throw new ProcessingError('Email and Password Required');
    }
    ...
}).catch(function(err) {
  if (err instanceof ProcessingError) {
    return res.status(422).send({ error: err.message });
  }
  next(err);
});