Express Error Handling Opinion&最佳实践

时间:2017-07-04 00:16:48

标签: node.js express error-handling

我有更多关于错误处理NodeJs Express应用程序的代码体系结构问题。我不确定错误处理的最佳模式是什么。在这方面,应该将哪些情况视为错误。例如,401 Unauthorized代码是否被视为错误,即使在发送错误凭据时预期会出现此响应?

使用时:

//app.js file
app.use(err, req, res, next){}

我通常倾向于只在这里放置5xx错误,这些错误代表无法找到数据库或没有网络连接问题或功能失败的情况。至于其余部分,我会通过显式编码res.status(xxx).send();或类似的东西从控制器手动发回状态代码,例如401。但我正在做的事情背后的问题是我倾向于重复自己,并且必须将记录分散在应用程序中。我的方法很好吗?我应该为不同的状态代码范围创建多个错误处理中间件吗?我需要一个意见

1 个答案:

答案 0 :(得分:2)

我更喜欢将middleware与您的自定义错误类一起使用来处理此问题。

让我们看一个错误类,其中包含自定义错误消息,http状态代码和logLevel,如果您使用记录器。

module.exports = class ApiCalError extends Error {
  constructor (message, status, logLevel) {

    // Calling parent constructor of base Error class.
    super(message);

    // Capturing stack trace, excluding constructor call from it.
    Error.captureStackTrace(this, this.constructor);

    // Saving class name in the property of our custom error as a shortcut.
    this.name = this.constructor.name;

    // You can use any additional properties you want.
    // I'm going to use preferred HTTP status for this error types.
    // `500` is the default value if not specified.
    this.status = status || 400;

    this.logLevel = logLevel || 'warn';

  }

  toResponseJSON () {
    return {
        success: false,
        message: this.message
    }
  }
};

现在,让我们来看一下控制器。我们只从该控制器发送了成功的响应,并将自定义错误传递给中间件。

  exports.Login = function(req, res, next) {
        const validationResult = validateLoginForm(req.body)
        if (!validationResult.success) {
            var err = new customError(validationResult.message, 400, 'warn')
            return next(err)
        } else {
            return passport.authenticate('local-login', (err, token, userData) => {
                if (err) {
                    if (err.name == 'IncorrectCredentialsError' || err.name == 'EmailNotVerified') {
                        var error = new customError(err.message, 400, 'warn')
                        return next(error)
                    }
                    return next(err)
                }
                return res.json({
                    success: true,
                    message: 'You have successfully logged in!',
                    token,
                    user: userData
                })
            })(req, res, next)
        }
    }

现在,让我们来看看记录器和错误处理程序中间件。这里,logger将在api中记录错误并将错误传递给错误处理程序。然后,这些函数将用于app.use()

    // Import library

    var Logger = function(logger) {
        return function(err, req, res, next) {
            var meta = {
                path: req.originalUrl,
                method: req.method,
                'user-agent': req.headers['user-agent'],
                origin: req.headers.origin 
            }
            if (err instanceof customError) {
                logger.log(err.logLevel, err.message, meta)
                return next(err)
            } else {
                logger.log('error', err.message, meta)
                return next(err)
            }
        }   
    }
    var ErrorHandler = function() {
        return function(err, req, res, next) {
            if (err instanceof customError) {
                return res.status(err.status).json(err.toResponseJSON())
            }else{
                return res.status(500).json({
                    success: false,
                    message: err.message
                })
            }
        }
    }

    module.exports = {
        Logger,
        ErrorHandler
    }