3

在查看了Twisted 的DeferredHeavyLifters Deferred Library之后,我注意到如果先前的结果值是Failure该类的实例,则会触发 errbacks。这让我开始思考:是否有任何特殊原因返回一个特殊对象来表示错误,而不是仅仅抛出一个错误。

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

  1. 可以抛出任何值。
  2. 如果抛出的值没有被捕获,它会向上传播调用堆栈。
  3. 不需要特殊FailureError课程。
  4. 它使回调看起来更像同步代码。
  5. 可以在调用堆栈的任何级别处理异常。

我注意到的一些缺点是:

  1. 尝试代码块并捕获错误可能会导致代码性能下降。
  2. 如果未捕获到异常,则它会停止执行回调链的其余部分。
  3. 与使用 try catch 块相反,异步编程是必不可少的。

我正在尝试权衡可能性并找出哪种报告错误的方法更适合这种情况。

4

2 回答 2

1

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

Failure也是将回溯状态与异常保持在一起的好地方。Python异常通常不携带堆栈信息,所以如果你只有一个异常,你是找不到它在哪里引发的。每当您想要处理except捕获它的块之外的异常时,这可能是一个主要缺点。

最后,能够返回 aFailure启用了这个简单、常用的模式:

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

    handleThisCase(reason)

someDeferred.addErrback(handleOneErrorCase)

这经常出现在Deferred-using 代码中。它很方便,恰好在 CPython 上性能更高一些,并且还具有reason保留原始堆栈信息的优点(如果错误处理程序重新引发异常,则该位置的堆栈将替换原始堆栈,掩盖异常的原始原因)。

于 2012-06-19T12:46:30.873 回答
0

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

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

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

于 2012-06-19T05:49:52.973 回答