最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Custom error formatting - Stack Overflow

programmeradmin1浏览0评论

I have implemented my own custom error:

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

And what I'm missing is to make it display itself on screen as it would when a regular unhanded error occurs, i.e. if we do throw new Error('Hello!'), we get output:

throw new Error('Hello!');
^

Error: Hello!
    at Object.<anonymous> (D:\NodeJS\tests\test1.js:28:7)
    at Module._pile (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

Now I want the same nicely formatted output when I'm doing this:

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

but instead I'm getting:

{ [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._pile (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!' }

What else needs to be done to make console.log(e) output the same nicely formatted presentation for MyError automatically, without having to use explicit e.stack reference?

UPDATE: At first I saw some remendations regarding method toJSON to be implemented, which I did, but it didn't quite work. I assume there must be an overridable method that console.log uses in order to format an error object, but what is it then?

I have implemented my own custom error:

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

And what I'm missing is to make it display itself on screen as it would when a regular unhanded error occurs, i.e. if we do throw new Error('Hello!'), we get output:

throw new Error('Hello!');
^

Error: Hello!
    at Object.<anonymous> (D:\NodeJS\tests\test1.js:28:7)
    at Module._pile (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

Now I want the same nicely formatted output when I'm doing this:

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

but instead I'm getting:

{ [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._pile (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!' }

What else needs to be done to make console.log(e) output the same nicely formatted presentation for MyError automatically, without having to use explicit e.stack reference?

UPDATE: At first I saw some remendations regarding method toJSON to be implemented, which I did, but it didn't quite work. I assume there must be an overridable method that console.log uses in order to format an error object, but what is it then?

Share edited Nov 22, 2015 at 20:00 vitaly-t asked Nov 18, 2015 at 22:09 vitaly-tvitaly-t 26k17 gold badges127 silver badges150 bronze badges 6
  • Well, I assume it's just the error being logged different when you just throw it, instead of logging the error object. So if you just threw it then maybe you'd get the same format. Anyway, looking at your properties, you could always make your own log function that matches that format. – MinusFour Commented Nov 18, 2015 at 22:23
  • @MinusFour, ...my own log function? Would you please clarify? How will it make console.log(e) output the error properly formatted? – vitaly-t Commented Nov 18, 2015 at 22:30
  • but, errors do show up nicely by default in the console... with callstack and everything... – Sebas Commented Nov 21, 2015 at 5:00
  • @Sebas only when left unhandled. When you handle them and use console.log, they e up ugly. – vitaly-t Commented Nov 22, 2015 at 19:57
  • @vitaly-t why don't you use console.error() instead? – Sebas Commented Nov 22, 2015 at 22:46
 |  Show 1 more ment

4 Answers 4

Reset to default 4 +50

Instead of overriding the toJSON method (or, toString as is frequently assumed), you should override inspect, which is used when trying to console.log an object in V8.

For example:

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

should probably do the trick.

Try this

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

If you execute this code in the console of your browser it will display like this:

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)

If I understand correctly what you want is to print the stack of your error?

I have written a function to handle uncaughtException Errors so that the server does not stops on unhandled errors.

Function

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.
  });
}

Output

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)

Hope This Helps.

It's not very remended, but you could always hook the console.log handler:

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

Fiddle: http://jsfiddle/xagpf5ff/

发布评论

评论列表(0)

  1. 暂无评论
ok 不同模板 switch ($forum['model']) { /*case '0': include _include(APP_PATH . 'view/htm/read.htm'); break;*/ default: include _include(theme_load('read', $fid)); break; } } break; case '10': // 主题外链 / thread external link http_location(htmlspecialchars_decode(trim($thread['description']))); break; case '11': // 单页 / single page $attachlist = array(); $imagelist = array(); $thread['filelist'] = array(); $threadlist = NULL; $thread['files'] > 0 and list($attachlist, $imagelist, $thread['filelist']) = well_attach_find_by_tid($tid); $data = data_read_cache($tid); empty($data) and message(-1, lang('data_malformation')); $tidlist = $forum['threads'] ? page_find_by_fid($fid, $page, $pagesize) : NULL; if ($tidlist) { $tidarr = arrlist_values($tidlist, 'tid'); $threadlist = well_thread_find($tidarr, $pagesize); // 按之前tidlist排序 $threadlist = array2_sort_key($threadlist, $tidlist, 'tid'); } $allowpost = forum_access_user($fid, $gid, 'allowpost'); $allowupdate = forum_access_mod($fid, $gid, 'allowupdate'); $allowdelete = forum_access_mod($fid, $gid, 'allowdelete'); $access = array('allowpost' => $allowpost, 'allowupdate' => $allowupdate, 'allowdelete' => $allowdelete); $header['title'] = $thread['subject']; $header['mobile_link'] = $thread['url']; $header['keywords'] = $thread['keyword'] ? $thread['keyword'] : $thread['subject']; $header['description'] = $thread['description'] ? $thread['description'] : $thread['brief']; $_SESSION['fid'] = $fid; if ($ajax) { empty($conf['api_on']) and message(0, lang('closed')); $apilist['header'] = $header; $apilist['extra'] = $extra; $apilist['access'] = $access; $apilist['thread'] = well_thread_safe_info($thread); $apilist['thread_data'] = $data; $apilist['forum'] = $forum; $apilist['imagelist'] = $imagelist; $apilist['filelist'] = $thread['filelist']; $apilist['threadlist'] = $threadlist; message(0, $apilist); } else { include _include(theme_load('single_page', $fid)); } break; default: message(-1, lang('data_malformation')); break; } ?>