node.js - 处理不同类型的错误时出错

ric*_*wol 5 node.js express

我在Express中编写了一系列REST API,并希望编写一种强大而一致的方法来处理错误并将其呈现给用户.到目前为止,我使用的中间件如下所示:

app.use(function(req, res, next){
    res.render('404', { status: 404, error: 'not_found', error_description: 'the url '+req.url+' could not be found' });
});

app.use(function(err, req, res, next) {
    switch (err.name) {
        case 'CastError':
            res.status(400);
            return res.send({code:400, error: 'cast_error', error_description: err});
        default:
            console.log(err);
            return res.send({code:500, error: 'internal_error', error_description: 'something went horribly wrong!'});
    }
});
Run Code Online (Sandbox Code Playgroud)

现在问题在于错误可能来自应用程序的任何部分.例如,Mongoose会触发"CastError"之类的错误,可能会出现一般系统错误(无法连接到数据库),还会出现用户验证错误.

现在有些错误我想向用户显示一条消息(例如验证错误或告诉他们API请求有什么问题),而其他我想要隐藏用户的错误.

所以看一下验证错误:

throw new Error('not a valid project id');
Run Code Online (Sandbox Code Playgroud)

此刻,它只是作为一般500错误而被捕获,并且没有向用户显示有用的消息.如何将上述错误与一般系统错误区分开来,以便对它们进行不同的处理?是否有我可以使用的错误类型属性(可能是err.name).如果是这样,我该如何使用它?

概念创意(obv不起作用):

throw new Error('validation', 'not a valid project id');
Run Code Online (Sandbox Code Playgroud)

要么

throw new Error('not a valid project id').name('validation');
Run Code Online (Sandbox Code Playgroud)

c.P*_*.u1 7

Errors是对象,可以分配其他属性.您可以在构造错误后为错误添加更多属性.还要注意,操作数throw不必是一个Error,它可以是任何其他对象.

var validationError = new Error('Not a valid project ID');
validationError.type = 'validation';
throw validationError;
Run Code Online (Sandbox Code Playgroud)

更好的选择是使用继承自定义的错误类Error.

function ValidationError(message) {
    if(!(this instanceof ValidationError)) {
        return new ValidationError(message);
    }
    var err = this.err = Error.call(this, message);
    this.message = message;

    Object.defineProperty(this, 'stack', {
        get: function () {
            return err.stack; 
        }
    });

}
ValidationError.prototype = Object.create(Error.prototype, {constructor: ValidationError});
Run Code Online (Sandbox Code Playgroud)

此方法允许您ValidationError使用instanceof运算符区分s与其他错误.这是koa应用程序的摘录:

app.use(function *() {
    try {
            if(this.method != 'GET') {
                yield this.connection.beginTransaction();
                yield *next;
                yield this.connection.commit();
            } else {
                yield *next;
            }
        } catch(err) {
            if(err instanceof ValidationError) {
                this.body = err.message;
                this.status = 422;
            } else {
                throw err; //let the framework notify the client of 500 Internal Server errors
            }
            if(this.method != 'GET') {
                yield this.connection.rollback();
            }
        }
});
Run Code Online (Sandbox Code Playgroud)