3 回答
TA贡献1802条经验 获得超10个赞
此行为完全类似于同步抛出:
try{
throw new Error();
} catch(e){
// handle
}
// this code will run, since you recovered from the error!
那是.catch要从错误中恢复的一半。可能需要重新抛出信号以指示状态仍然是错误:
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条经验 获得超6个赞
.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" });
});
添加回答
举报