【问题标题】:What's the advantage of returning exceptions over using try catch blocks in async callback chain?与在异步回调链中使用 try catch 块相比,返回异常有什么优势?
【发布时间】:2012-06-19 05:39:57
【问题描述】:

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

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

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

我注意到的一些缺点是:

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

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

    def handleOneErrorCase(reason):
        if not thisCaseApplies(reason):
            return reason
    
        handleThisCase(reason)
    
    someDeferred.addErrback(handleOneErrorCase)
    

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

      • 这很明显。这是因为该函数是在 setTimeout 函数中调用的,该函数本身会捕获所有错误。简单的解决方法是创建一个捕获所有错误并触发回调的闭包。因此,不是将函数传递给setTimeout,而是传递包装函数的闭包。我真正想知道的是在闭包中使用 try catch 块或检查包装函数的返回值是否更好。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-11
      • 2021-07-13
      • 2019-10-23
      • 2011-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多