如何在保留 JavaScript 调试器功能的同时进行优雅的异常处理

How to do elegant exception handling while retaining JavaScript debugger capabitilities

本文关键字:异常处理 保留 JavaScript 调试器 功能      更新时间:2023-09-26

你知道JavaScript基本上可以抛出任何对象甚至原始对象作为例外:

throw 1;
throw { text: "hello" }

可悲的是,像 Firefox 这样的调试器会将异常记录到控制台,包括指向代码行的链接,如果我们抛出内置Error对象,则会抛出异常。

为了解决这个限制,我想:为什么我不覆盖toString,我给出一个异常实例作为构造函数Error参数,以便异常将隐式转换为string

var ArgumentException = function(args) {
   this._argName= args.argName;
}
ArgumentException.prototype = {
    _argName: null,
    get argName() { return this._argName; },
    toString: function() { 
       return "ArgumentException was thrown. Affected argument: " + this.argName;
    }
};
throw Error(new ArgumentException({ argName: "someArgument" }));

显然,上面的代码列表是对真实案例的简化。

好的,这有效并解决了整个问题。

但这扼杀了使用异常的目的,因为try/catch将无法按类型处理异常:

try
{
    throw Error(new ArgumentException({ argName: "someArgument" }));
} catch(e) {
    if(e instanceof ArgumentException) {
         // This will happen never! "e" will hold a Error instance!!!!
    }
}

你如何解决这个问题?事实上,这是 Web 浏览器调试器的问题,而不是实际 JavaScript 的问题,但由于调试是任何开发周期中的重要点,因此应该认真对待。

提前谢谢你。

编辑

我想分享我的另一个结论:

try
{
    debugger;
    throw new ArgumentException({ argName: "someArgument" });
} catch(e) {
    if(e instanceof ArgumentException) {
    }
}

上述解决方案会将异常记录到调试器控制台,但它会在引发调试器之前停止调试器。好的,您没有获得指向确切行的链接,但调试器会停在那里,因此您可以知道将在哪里抛出异常。

为什么不让你的异常继承自错误

function ArgumentException(data) {
    this.name = "ArgumentException";
    this.message = arguments.length ? 'Affected argument: ' + data.argName : "Illegal argument";
}
// set up inheritance
ArgumentException.prototype = Object.create(Error.prototype);
ArgumentException.prototype.constructor = ArgumentException;
// use it 
try {
    throw new ArgumentException({argName: "someArgument"});
} catch(e) {
    if(e instanceof ArgumentException) {
        console.log(e); // hi there
    }
}
// see it normally
throw new ArgumentException({argName: "someOtherArgument"});
// ArgumentException: Affected argument: someOtherArgument

有关更多信息,请查看 MDN 上的自定义错误类型