我正在使用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!'});
}
});
现在出现的问题是错误可能来自应用程序的任何部分。例如,Mongoose会触发“CastError”之类的错误,可能会出现一般系统错误(无法连接到数据库),还会出现用户验证错误。
现在有些错误我想向用户显示一条消息(例如验证错误或告诉他们API请求有什么问题),而其他人则想要隐藏用户。
所以看一下验证错误:
throw new Error('not a valid project id');
此刻,这只是因为一般性500错误而被捕获,并且没有向用户显示有用的消息。如何将上述错误与一般系统错误区分开来,以便对它们进行不同的处理?是否有我可以使用的错误类型属性(可能是err.name)。如果是这样,我该如何使用它?
概念创意(obv不起作用):
throw new Error('validation', 'not a valid project id');
或者
throw new Error('not a valid project id').name('validation');
答案 0 :(得分:7)
Error
是对象,可以分配其他属性。您可以在构造错误后为错误添加更多属性。另请注意,throw
的操作数不必是Error
,它可以是任何其他对象。
var validationError = new Error('Not a valid project ID');
validationError.type = 'validation';
throw validationError;
更好的选择是使用从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});
此方法可让您使用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();
}
}
});
答案 1 :(得分:4)
您应该考虑使用现有的npm模块,例如http-errors或boom。至少在抛出自己的错误时,这些将使得在响应中获得良好的HTTP语义变得容易。