当对任何模型方法或助手进行调用失败时,Sails 会抛出一个 JavaScript Error 实例,其属性可用于诊断出错的原因。
Waterline 会规范化这些 Error 实例,使用一致的 err.name
值对其进行分类,并在适用时使用 err.code
。
try {
await Something.create({…});
} catch (err) {
// err.name
// err.code
// …
}
全局错误处理虽然胜于无,但通常都不够。(“这不是一个有效的用户名”和“我们目前无法创建新用户”之间存在很大差异。)为了适当地处理不同类型的错误,您需要能够以细粒度的方式检查它们。
幸运的是,Sails 提供了一些语法糖来开箱即用地实现这一点,无需使用 try… catch:.intercept() 和 .tolerate()。
await Something.create({…})
.intercept((err)=>{
// Return a modified error here (or a special exit signal)
// and .create() will throw that instead
err.message = 'Uh oh: '+err.message;
return err;
});
属性 | 类型 | 详情 |
---|---|---|
name | 错误的广泛分类。 例如: 'UsageError' |
|
message | 参见 .message。 | |
stack | 参见 .stack。 | |
code | 有时包含的更具体的错误分类。 例如: 'E_UNIQUE' |
当使用与 Waterline 交互的代码(通常通过模型方法)时,您可能会遇到几种不同的错误。
当错误具有 name: 'UsageError'
时,这表示 Waterline 方法使用不正确,或使用无效的选项执行(例如,尝试创建违反模型 高级验证规则 之一的新记录)。
此类错误可能来自任何模型方法。
err.name === 'UsageError'
适配器错误通常表示底层适配器中存在问题,而不是请求本身。当数据库脱机时、存在权限问题时、由于某些特定于数据库的边缘情况,或者(更少见)适配器中的错误,都可能发生这种情况。此类错误将具有 name: 'AdapterError'
。
此类错误可能来自任何模型方法。
err.name === 'AdapterError'
当应该唯一的值与数据库中另一条记录的值匹配时,就会发生唯一性错误。虽然这被认为是适配器错误,但它有自己的 code
来将其与普通适配器错误区分开来:code: 'E_UNIQUE'
。
此类错误只能来自 .create()
、.update()
、.addToCollection()
和 .replaceCollection()
模型方法。
err.code === 'E_UNIQUE'
在您的 Sails 应用程序中执行此操作的确切策略取决于您是否使用 await
、Promise 或回调。
await
处理错误处理尝试从操作内部创建新用户时可能发生的各种错误
await User.create({ emailAddress: inputs.emailAddress })
// Uniqueness constraint violation
.intercept('E_UNIQUE', (err)=> {
return 'emailAlreadyInUse';
})
// Some other kind of usage / validation error
.intercept({name:'UsageError'}, (err)=> {
return 'invalid';
});
// If something completely unexpected happened, the error will be thrown as-is.
return exits.success();
如果您由于使用 Node.js <= v7.9 而无法使用 await
,那么请做好准备:当使用回调或 Promise 链而不是 await
时,错误处理的工作方式略有不同。
如果可能,请使用
await
!它对您的应用程序更安全,您的代码将更简洁,您也会更快乐。
例如,如果您使用 Promise 链,则可以使用以下方法处理尝试创建新用户时可能发生的各种错误
User.create({
emailAddress: req.param('emailAddress')
})
.then(function (){
res.ok();
})
// Uniqueness constraint violation
.catch({ code: 'E_UNIQUE' }, function (err) {
res.sendStatus(409);
})
// Some other kind of usage / validation error
.catch({ name: 'UsageError' }, function (err) {
res.badRequest();
})
// If something completely unexpected happened.
.catch(function (err) {
res.serverError(err);
});
这是同一个示例,但使用传统的 Node.js 回调而不是 Promise 链编写
User.create({
emailAddress: req.param('emailAddress')
})
.exec(function (err){
if (err && err.code === 'E_UNIQUE') {
return res.sendStatus(409);
} else if (err && err.name === 'UsageError') {
return res.badRequest();
} else if (err) {
return res.serverError(err);
}
return res.ok();
});
但请注意未捕获的异常!