繁体   English   中英

JavaScript中错误捕获的正确粒度是什么?

[英]What is the right granularity of error catching in JavaScript?

我以前在我的JS类的任何方法中都有一个try...catch

var MyConstructor = function() {
    this.init = function() {
        try {
            // the method code...
        } catch(error) {
            // the error manager log actions
        }
    };
    // other methods, with the same try/catch usage
};

这样,保持代码接口相对简单,我认为我的代码中的任何错误都会被捕获并记录/管理。

var myInstance = new MyConstructor();

相反,每个脚本是否足够一个全局捕获块? 关心每个可能(或值得注意的)错误,在我看来应该知道应用程序中发生的每个错误:

// no try...catch inside the classes, but only a global try...catch per script:
try {
    var myInstance = new MyConstructor();
} catch(error) {
    /*
        log in the needed environment
        (e.g. client-side, via console, or to the server...)
    */
}

我搜索并阅读Stackoverflow上的线程以及有关JavaScript错误管理的非凡资源。
在这个阶段,我感兴趣的是找到找到所有错误的最佳方法,而不是管理它们以获得用户界面的优雅行为。
这不是正确的方法吗? 我对任何建议持开放态度。

经验法则是你应该问自己“谁应该在逻辑上处理问题?” 并坚持这一点。

重要的是要记住,当你编写一段代码时,你实际上写了一份合同,描述代码的各个部分是如何交互的。 例如,在您创建MyConstructor实例的情况下,为什么会失败? 它产生了什么样的承诺? 最重要的是,谁应该处理它失败?

一些例子

假设我们有一个类Car ,而Car实例有一个方法drive(x)

当您调用drive(x)Car会向右移动x位置。

动作drive(x)可能会失败,例如,如果Car已经位于屏幕边缘,或者Car没有燃料。

我们刚刚将drive定义为“汽车向右移动x个位置”,这意味着汽车希望能够完成驱动器操作并且无法完成它在逻辑上是一个例外。 在这种情况下,很明显,处理异常的是驱动器的调用者而不是汽车本身,因为它不必知道它正在驱动的环境。 更好的是,来电者不应该试图将车开出边缘或没有任何燃料。

在另一个案例中

让我们说在同一个例子中, Environment是一个包含汽车的类,它有一个moveCars()方法,根据一些内部包含的逻辑移动环境中的所有汽车。 Environment由程序使用,该程序期望它包含所有移动逻辑。 我们在moveCars()中使用了一些算法来确保汽车不会碰撞。

我们可能有一些我们在moveCars()方法中没有想到的边缘情况,或者由于某些假设而不应该发生的情况,但环境用户希望它包含所有移动逻辑,这意味着何时发生异常它本身应该处理它。

那么,总体战略是什么?

您应该根据运行代码的组件的职责处理异常。

这个问题实际上不仅限于JavaScript。 异常捕获的正确粒度取决于可能具有异常的模块和函数的正确粒度。 精心设计的模块或功能应该与明确定义的合同( DbC )绑定。 只要明确建立合同,异常处理问题就会变得容易多了。

关于合同的三个重要问题是:合同期望什么? 合同保证什么? 合同维持什么? 例如,假设函数divide(a, b)返回a / b 此函数期望b非零( 前置条件 ),如果b恰好为零,则此函数抛出异常而不是catch异常。 因为调用者有责任保证传递参数的有效性,这是合同的一部分。 除此之外, divide函数中可能发生的所有其他错误都应该被捕获,因为这是它自己的责任。 作为合同的另一部分, divide promise divide返回一个值(即商)乘以b 应该等于a (称为后置条件 )。

异常处理可能很复杂。 函数(或模块)可以选择捕获异常,如果它在其职责范围内,或者选择不捕获超出其职责的异常,或选择先捕获异常,处理它,然后在包装异常后重新抛出调用者作为调用者层的例外。

总而言之,异常处理不是一个独立的问题,它是整个系统设计的一部分。 一旦设计师合理地将复杂系统分成相对简单的模块,每个模块都具有良好的抽象/接口和明确定义的合同/责任,处理异常的方式和位置应该是不言自明的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM