自定义错误格式化

8

我已经实现了自己的自定义错误:

function MyError() {
    var temp = Error.apply(this, arguments);
    temp.name = this.name = 'MyError';
    this.stack = temp.stack;
    this.message = temp.message;
}

MyError.prototype = Object.create(Error.prototype, {
    constructor: {
        value: MyError,
        writable: true,
        configurable: true
    }
});

我想要的是将其显示在屏幕上,就像处理常规错误时一样。例如,如果我们执行throw new Error('Hello!'),则会输出:

throw new Error('Hello!');
^

Error: Hello!
    at Object.<anonymous> (D:\NodeJS\tests\test1.js:28:7)
    at Module._compile (module.js:425:26)
    at Object.Module._extensions..js (module.js:432:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:313:12)
    at Function.Module.runMain (module.js:457:10)
    at startup (node.js:138:18)
    at node.js:974:3

现在我希望在进行以下操作时能够获得相同的格式化输出:
try {
    throw new MyError("Ops!");
} catch (e) {
    console.log(e);
}

但是我却得到了以下的结果:
{ [MyError: Ops!]
  name: 'MyError',
  stack: 'MyError: Ops!\n    at MyError.Error (native)\n    at new MyError (D:\\NodeJS\\tests\\test1.js:2:22)\n    at Object.<anonymous> (D:\\NodeJS\\tests\\test1.js:22:11)\n    at Module._compile (module.js:425:26)\n    at O
bject.Module._extensions..js (module.js:432:10)\n    at Module.load (module.js:356:32)\n    at Function.Module._load (module.js:313:12)\n    at Function.Module.runMain (module.js:457:10)\n    at startup (node.js:138:18)\n
at node.js:974:3',
  message: 'Ops!' }

还有什么需要做才能使console.log(e)自动输出与MyError相同的漂亮格式化呈现,而不必使用显式的e.stack引用?
更新:起初我看到一些关于实现方法toJSON的建议,我确实做了,但它并没有完全奏效。我认为console.log使用一个可重写的方法来格式化错误对象,但是这个方法是什么呢?

嗯,我认为只是在抛出错误时记录的方式不同,而不是记录错误对象。因此,如果你只是抛出它,那么也许你会得到相同的格式。无论如何,看着你的属性,你总可以创建自己的日志函数来匹配该格式。 - MinusFour
@MinusFour,...我的自己的log函数?你能否澄清一下吗?它如何使console.log(e)输出正确格式的错误信息? - vitaly-t
但是,默认情况下,错误会在控制台中很好地显示出来...带有调用堆栈和其他信息... - Sebas
只有在未处理时,@Sebas才会出现。当您处理它们并使用console.log时,它们会变得丑陋。 - vitaly-t
@vitaly-t 为什么不使用 console.error() 呢? - Sebas
在这种情况下,@Sebas没有任何影响,输出完全相同。 - vitaly-t
4个回答

4

不要覆盖toJSON方法(或者像通常假定的那样,覆盖toString方法),应该覆盖inspect方法,在尝试在V8中console.log一个对象时会使用到该方法。

例如:

MyError.prototype.inspect = function () {
    return this.stack;
};

应该可以解决问题。


这正是我在寻找的答案!非常感谢你! - vitaly-t

0

这并不是很推荐的做法,但你可以挂钩 console.log 处理程序:

var oldhandler = console.log;
console.log = function () {
    if (typeof(arguments[0].stack) != "undefined" && arguments[0] instanceof(Error) && typeof(arguments[0].stack) != "undefined") {
        oldhandler.apply(console,[arguments[0].stack]);
    } else {
        oldhandler.apply(console,arguments);
    }                                                                                                                              
}

try {
    throw new Error("qweqew");
} catch (ex) {
    console.log(ex);
}

代码嵌片: http://jsfiddle.net/xagpf5ff/


0

试试这个

try {
  throw new MyError("Ops!");
} catch (e) {
  console.log(e.stack);
}

如果您在浏览器控制台中执行此代码,它将显示如下:
MyError: Ops!
  at MyError.Error (native)
  at new MyError (<anonymous>:3:22)
  at <anonymous>:18:11
  at Object.InjectedScript._evaluateOn (<anonymous>:875:140)
  at Object.InjectedScript._evaluateAndWrap (<anonymous>:808:34)
  at Object.InjectedScript.evaluate (<anonymous>:664:21)

如果我理解正确,您想要打印出错误的堆栈吗?


输出很好,没错,但我希望有一种方法可以自动地生成这样的输出,而不必明确引用 e.stack。有没有办法扩展 MyError 来实现这个功能?问题是,e 可能会引用其他错误,包括那些根本没有任何 stack 的错误。 - vitaly-t
我已经更新了我的问题底部部分以澄清这一点。 - vitaly-t

0
我编写了一个函数来处理未捕获的异常错误,以便服务器不会在未处理的错误上停止。 函数
function errorHandler (){
  process.on('uncaughtException', function (err) {
    console.log(err); // Displays the Error;
    console.error((new Date).toUTCString() + ' uncaughtException:', err.message); // Displays the Date and Error Message.
    console.error(err.stack);  // Stack in Which the error occurred.
  });
}

输出

ISODate("2015-07-28T04:56:20.000Z") uncaughtException: Cannot read property 'asset' of undefined

TypeError: Cannot read property 'asset' of undefined\n
 at /Path/file.js:31:31\n
 at /path/node_modules/mongodb/lib/mongo_client.js:436:11\n    
 at process._tickDomainCallback (node.js:463:13)

希望这能有所帮助。

简化我的问题:如何使 console.log 显示我的自定义错误格式良好? - vitaly-t

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接