3 回答

TA貢獻1802條經驗 獲得超10個贊
此行為完全類似于同步拋出:
try{
throw new Error();
} catch(e){
// handle
}
// this code will run, since you recovered from the error!
那是.catch要從錯誤中恢復的一半??赡苄枰匦聮伋鲂盘栆灾甘緺顟B仍然是錯誤:
try{
throw new Error();
} catch(e){
// handle
throw e; // or a wrapper over e so we know it wasn't handled
}
// this code will not run
但是,僅此一種方法對您而言不起作用,因為該錯誤將由以后的處理程序捕獲。真正的問題是,廣義的“ HANDLE ANYTHING”錯誤處理程序通常是一種不好的做法,在其他編程語言和生態系統中卻極少使用。因此,藍鳥提供了類型化和謂詞性的捕獲。
附加的優點是您的業務邏輯根本不需要(也不應該)知道請求/響應周期。決定客戶端獲取哪種HTTP狀態和錯誤不是查詢的責任,而隨著應用的增長,您可能希望將業務邏輯(如何查詢數據庫以及如何處理數據)與發送給客戶端的內容分開(什么http狀態代碼,什么文本和什么響應)。
這是我編寫您的代碼的方式。
首先,我將.Query拋出一個NoSuchAccountError,將其從Promise.OperationalErrorBluebird已經提供的子類化。如果您不確定如何將錯誤歸類,請告訴我。
我另外為其子類化AuthenticationError,然后執行類似的操作:
function changePassword(queryDataEtc){
return repository.Query(getAccountByIdQuery)
.then(convertDocumentToModel)
.then(verifyOldPassword)
.then(changePassword);
}
如您所見-它非常干凈,您可以閱讀文本,就像使用說明書一樣,了解過程中發生的情況。它也與請求/響應分開。
現在,我將從路由處理程序中這樣調用它:
changePassword(params)
.catch(NoSuchAccountError, function(e){
res.status(404).send({ error: "No account found with this Id" });
}).catch(AuthenticationError, function(e){
res.status(406).send({ OldPassword: error });
}).error(function(e){ // catches any remaining operational errors
res.status(500).send({ error: "Unable to change password" });
}).catch(function(e){
res.status(500).send({ error: "Unknown internal server error" });
});
這樣,邏輯就全部集中在一個地方,而如何為客戶處理錯誤的決定就都集中在一個地方,而且它們不會相互干擾。

TA貢獻1936條經驗 獲得超7個贊
.catch就像try-catch語句一樣工作,這意味著最后只需要一個捕獲即可:
repository.Query(getAccountByIdQuery)
.then(convertDocumentToModel)
.then(verifyOldPassword)
.then(changePassword)
.then(function(){
res.status(200).send();
})
.catch(function(error) {
if (/*see if error is not found error*/) {
res.status(404).send({ error: "No account found with this Id" });
} else if (/*see if error is verification error*/) {
res.status(406).send({ OldPassword: error });
} else {
console.log(error);
res.status(500).send({ error: "Unable to change password" });
}
});

TA貢獻1874條經驗 獲得超12個贊
我想知道是否存在一種方法可以根據錯誤以某種方式強制鏈條停止在某個點
不可以。除非您拋出一個冒泡直到結束的異常,否則您無法真正“終止”一條鏈。
他的模式的派生將不是區分錯誤類型,而是使用具有statusCode和body字段的錯誤,這些錯誤和字段可以從單個通用.catch處理程序發送。根據您的應用程序結構,他的解決方案可能會更干凈。
或者是否有更好的方法來構造它以獲得某種形式的分支行為
是的,您可以使用promises進行分支。但是,這意味著離開鏈并“返回”嵌套-就像您在嵌套的if-else或try-catch語句中所做的那樣:
repository.Query(getAccountByIdQuery)
.then(function(account) {
? ? return convertDocumentToModel(account)
? ? .then(verifyOldPassword)
? ? .then(function(verification) {
? ? ? ? return changePassword(verification)
? ? ? ? .then(function() {
? ? ? ? ? ? res.status(200).send();
? ? ? ? })
? ? }, function(verificationError) {
? ? ? ? res.status(406).send({ OldPassword: error });
? ? })
}, function(accountError){
? ? res.status(404).send({ error: "No account found with this Id" });
})
.catch(function(error){
? ? console.log(error);
? ? res.status(500).send({ error: "Unable to change password" });
});
添加回答
舉報