6

我曾经在try...catch我的 JS 类的任何方法中放置一个:

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();

相反,每个脚本一个全局 catch 块就足够了吗?关心抛出每个可能的(或值得注意的)错误,在我看来足以知道应用程序中发生的每个错误:

// 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 错误管理的大量在线资源。
在这个阶段,我感兴趣的是找到找到所有错误的最佳方法,而不是管理它们以获得用户界面的优雅行为。
这不是正确的方法吗?我愿意接受任何建议。

4

2 回答 2

2

The rule of thumb is that you should ask yourself "Who should deal with the problem logically?" and stick to that.

The important thing is to remember that when you write a piece of code you in fact write a contract describing of how bits and pieces of code interact. For example in your case when you create a MyConstructor instance why would it fail? What promise is made when it is generated? Most importantly, who should deal with it failing?

Some examples

Let's say that for example we have a class Car and instances of Car have a method drive(x).

When you call drive(x) the Car moves x places to the right.

The action drive(x) might fail, for example if the Car is already on the edge of the screen, or Car has no fuel.

We just defined drive as "the Car moves x places to the right" which means that the car expects to be able to complete the drive action and being unable to complete it is logically an exception. In this case it is quite obvious that the one handling the exception is the caller of drive and not the car itself since it wouldn't have to know what environment it is driving on. Even better, the caller should not attempt to drive the car off the edge or without fuel any way.

In another case

Let's say that in the same example Environment is a class that contains cars and it has a moveCars() method that moves all the cars in the environment according to some inner contained logic. Environment is used by a program that expects it to contain all the movement logic. We use some algorithm in moveCars() that is supposed to assure us that cars do not collide.

We might have some edge case we did not think of in our moveCars() method, or one that is not supposed to happen due to some assumption, however the user to environment expects it to contain all the move logic which means when an exception occurs it should deal with it itself.

So, what is the general strategy?

You should handle exceptions based on the responsibility the component running the code has.

于 2013-01-14T11:12:49.960 回答
1

这个问题实际上并不局限于 JavaScript。异常捕获的正确粒度取决于可能有​​异常的模块和函数的正确粒度。设计良好的模块或功能应该绑定到定义良好的合约(DbC)。只要明确建立契约,异常处理问题就会变得容易得多。

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

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

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

于 2013-01-14T12:09:25.710 回答