我对诺言仍然还很陌生,目前正在使用蓝鸟,但是在我不确定如何最好地处理它的情况下。
因此,举例来说,我在Express应用程序中有一个Promise链,如下所示:
repository.Query(getAccountByIdQuery) .catch(function(error){ res.status(404).send({ error: "No account found with this Id" }); }) .then(convertDocumentToModel) .then(verifyOldPassword) .catch(function(error) { res.status(406).send({ OldPassword: error }); }) .then(changePassword) .then(function(){ res.status(200).send(); }) .catch(function(error){ console.log(error); res.status(500).send({ error: "Unable to change password" }); });
所以我的行为是:
因此,当前的捕获量似乎并没有停止链接,这是有道理的,因此,我想知道是否有办法让我根据错误将链接强制停止在某个点,或者是否有更好的方法进行结构化,以获得某种形式的分支行为,例如if X do Y else Z。
if X do Y else Z
任何帮助都会很棒。
此行为完全类似于同步抛出:
try{ throw new Error(); } catch(e){ // handle } // this code will run, since you recovered from the error!
这.catch是能够从错误中恢复的一半。可能需要重新抛出信号以指示状态仍然是错误:
.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已经提供的子类中继承出来。如果您不确定如何将错误归类,请告诉我。
.Query
NoSuchAccountError
Promise.OperationalError
我另外为其子类化AuthenticationError,然后执行以下操作:
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" }); });
这样,逻辑就全部集中在一个地方,而如何处理客户端错误的决定就都集中在一个地方,而且它们不会相互干扰。