在异步回调链中使用try catch块返回异常有什么好处?

时间:2012-06-19 05:39:58

标签: javascript error-handling try-catch twisted deferred

在查看Twisted's Deferred classHeavyLifters Deferred Library之后,我注意到如果前一个结果值是Failure类的实例,则会触发错误。这让我想到:是否有任何特殊原因要求返回一个特殊对象来表示错误,而不是仅仅抛出一个错误。

根据我的推断,我觉得抛出错误会更好,因为:

  1. 可以抛出任何值。
  2. 如果未捕获抛出的值,它将向上传播调用堆栈。
  3. 不需要特殊的FailureError类。
  4. 它使回调看起来更像是同步代码。
  5. 可以在调用堆栈的任何级别处理异常。
  6. 我注意到的一些缺点是:

    1. 尝试代码块并捕获错误可能会导致代码性能下降。
    2. 如果未捕获异常,则会停止执行其余的回调链。
    3. 异步编程对于使用try catch块至关重要。
    4. 我正在尝试权衡赔率并找出在这种情况下哪种报告错误的方法更合适。

2 个答案:

答案 0 :(得分:1)

Twisted中的Failure类有许多方便的方法,使其有用,与Deferred中用于运行错误处理回调的功能无关。浏览API文档,您将找到有用的方法,例如格式化回溯和检查异常类型。 Failure也是一个方便的地方,可以放置一些非常严重的黑客,以便与twisted.internet.defer.inlineCallbacks的生成器和Cython的特殊支持代码进行良好的集成,从而产生微妙的不同异常。

Failure也是将追溯状态与异常保持在一起的好地方。 Python异常通常不携带堆栈信息,因此如果您只有异常,则无法找到它的引发位置。只要您想要处理捕获它的except块之外的异常,这可能是一个主要缺点。

最后,能够返回Failure可以实现这种简单,通用的模式:

def handleOneErrorCase(reason):
    if not thisCaseApplies(reason):
        return reason

    handleThisCase(reason)

someDeferred.addErrback(handleOneErrorCase)

这经常出现在Deferred - 使用代码。它很方便,在CPython上更具性能,并且还具有保留reason中原始堆栈信息的优点(如果异常由错误处理程序重新引发,则堆栈位于 点将替换原始堆栈,模糊了异常的原始原因。)

答案 1 :(得分:0)

错误通常在异步环境中通过回调返回,因为无法在异步函数之外捕获错误。例如,在javascript中尝试:

try {
    setTimeout(function() { throw new Error(); }, 0);
} catch (e) {
    console.log('Caught it.');
}

然后异常将被删除。这与以下事实有关:异步函数被重新注册,然后由不同堆栈中的事件循环调用,因此异常不会冒泡原始堆栈。