當呼叫任何模型方法或助手函數失敗時,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();
});
但請注意未捕獲的例外!