如何在Node.js中打印堆栈跟踪?

645

有人知道如何在Node.js中打印堆栈跟踪吗?

12个回答

747

任何Error对象都有一个stack成员,用于捕获它被构造的时刻。

var stack = new Error().stack
console.log( stack )
更简单地说:
console.trace("Here I am!")

2
或者只需添加系统模块,然后输入“sys.puts(new Error().stack)”(注意不要加引号)。 - sirhc
6
现在,sys已经被弃用。它已被'util'替代。 - Pindatjuh
13
+1 表示对于展示 new Error().stack 的做法也表示赞同,该方法适用于不想使用控制台的情况。这种方法可以展示调用堆栈信息。 - Evgeniy Berezovsky
1
trace 的一个优点是它显示当前行/上下文,而 stack 不会。如果您想手动创建该行,则可以在错误对象中找到该信息。 - studgeek
168
console.log(err.stack)和console.trace()的结果不同。err.stack会获得err对象自身的堆栈跟踪(按照我们通常想到异常的方式运行),而console.trace()将在调用console.trace()的点打印调用堆栈。因此,如果您捕获了一些由更深层代码抛出的错误,console.trace()将不包含该深层代码在堆栈跟踪中,因为该代码已经不在堆栈上了。然而,只要它抛出了一个Error对象,console.log(err.stack)将包含更深层的信息。 - d512

249

现在控制台上有一个专门的函数来实现这个功能:

console.trace()

15
请务必留意关于console.trace()上述评论 - Qix - MONICA WAS MISTREATED
13
默认情况下,这只会显示10个框架,您可以使用命令行参数来增加它,例如 --stack_trace_limit=200 - Michael
2
如果您想要输出到日志文件,该怎么处理? - Ya.
2
这似乎不能与 Promises 和 async/await 一起使用,是吗? - bluenote10

147

正如已经回答的那样,你可以简单地使用trace命令:

console.trace("I am here");

然而,如果您正在搜索如何记录异常的堆栈跟踪,只需记录异常对象即可。

try {  
  // if something unexpected
  throw new Error("Something unexpected has occurred.");     

} catch (e) {
  console.error(e);
}

它将记录:

错误:发生了意外情况。
    在 main (c:\ Users \ Me \ Documents \ MyApp \ app.js:9:15)
    在 Object。 (c:\ Users \ Me \ Documents \ MyApp \ app.js:17:1)
    在 Module._compile(module.js:460:26)
    在 Object.Module._extensions..js (module.js:478:10)
    在 Module.load(module.js:355:32)
    在 Function.Module._load(module.js:310:12)
    在 Function.Module.runMain(module.js:501:10)
    在启动时(node.js:129:16)
    在 node.js 中:814:3


如果您的Node.js版本小于6.0.0,仅记录异常对象将不足以应对此问题。在这种情况下,它只会打印:

[Error:Something unexpected has occurred。]

对于Node版本< 6,请使用 console.error(e.stack)而不是 console.error(e)来打印错误消息加上完整的堆栈,就像当前的Node版本一样。


注意:如果异常被创建为字符串,如 throw“myException”,则无法检索堆栈跟踪,并且记录 e.stack 将产生< strong>未定义的结果。

为了安全起见,您可以使用

console.error(e.stack || e);

它适用于旧版和新版 Node.js。


“console.error(e)” 不会打印出 e 对象中的所有内容,包括 e.stack 吗? - drmrbrewer
1
@drmrbrewer,感谢您指出这一点。在Node 4.x和7.x之间(可能是V8的变化),行为似乎已经改变了。我已经更新了我的答案。 - Zanon
1
@drmrbrewer确认这种行为在6.0.0版本中发生了变化。 - Zanon
你有这个行为变化的参考资料吗?我仍然看到(使用节点6.9.4),console.error(e)只打印简短的消息。我怀疑这是因为它打印了etoString表示形式,而etoString仅返回消息而没有其他内容:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/toString - drmrbrewer
@drmrbrewer 请尝试安装 n 在您的计算机上测试不同的Node版本,或者查看 这个使用 Node 7.4 的测试 并将其与 Node 0.8 进行比较。我无法获取最后一个的永久链接,但运行 console.error(new Error("test")) 以查看差异。关于此更改的参考资料,我在Node的变更记录中找不到。它似乎是V8的更改,但我也无法确认。 - Zanon
4
抱歉,我刚刚发现了一些至关重要的东西。请查看我对相关帖子的评论:https://dev59.com/0lgQ5IYBdhLWcg3wlk_P#ldjonYgBc1ULPQZFgI4h。似乎仅记录错误本身确实会显示完整的错误内容,但尝试将其与其他文本连接(如字符串)会导致仅使用简短的消息部分。有了这个认识,一切都更加清晰明了。 - drmrbrewer

41

为了以更易读的方式在控制台中打印Error的堆栈跟踪:

console.log(ex, ex.stack.split("\n"));

示例结果:

[Error] [ 'Error',
  '    at repl:1:7',
  '    at REPLServer.self.eval (repl.js:110:21)',
  '    at Interface.<anonymous> (repl.js:239:12)',
  '    at Interface.EventEmitter.emit (events.js:95:17)',
  '    at Interface._onLine (readline.js:202:10)',
  '    at Interface._line (readline.js:531:8)',
  '    at Interface._ttyWrite (readline.js:760:14)',
  '    at ReadStream.onkeypress (readline.js:99:10)',
  '    at ReadStream.EventEmitter.emit (events.js:98:17)',
  '    at emitKey (readline.js:1095:12)' ]

如果你愿意将错误信息打印到标准错误输出,可以使用 console.error(e)。它会为你打印出堆栈跟踪信息。 - undefined

12

@isaacs的答案是正确的,但如果你需要更具体或更简洁的错误堆栈,可以使用这个函数:

function getCleanerStack() {
   var err = new Error();
   Error.captureStackTrace(err, getCleanerStack);
    
   return err.stack;
}

这个函数直接受到 NodeJS 中的 console.trace 函数的启发。

源代码: 最新版本旧版本


4
只显示当前行的堆栈信息(而不是错误发生的那一行),意味着代码不能运行。更正确的答案应该是 err.stack - Clocher Zhong
14
getStack未定义 - Druska
第三行应该使用 getCleanerStack 而不是 getStack - kikon

10
在v15.12.0版本中,有多种方法可以实现这一点,
1. console.trace(anything)
2. Error.captureStackTrace(Object)
3. console.log(new Error().stack)
4. Try Catch - Use console.log(e), where `e` is catched by catch block

甚至更好的方法是在任何 JavaScript 代码中使用stacktracejs


5

尝试使用Error.captureStackTrace(targetObject[, constructorOpt])

const myObj = {};
function c() {
  // pass
}

function b() {
    Error.captureStackTrace(myObj)
    c()
} 

function a() {
    b()
}

a()

console.log(myObj.stack)

函数ab被捕获在错误堆栈中并存储在myObj中。


3
如果你想让一个错误具有 stack 属性,你需要在 Node 版本大于等于 6 的情况下调用 Error.captureStackTrace(error) - cjbarth
请注意,如果您不希望调用Error.captureStackTrace的框架显示在堆栈跟踪中,则可以通过将其作为constructorOpt参数传递来省略它。 - Ullauri

3

获取函数调用者的详细信息:

/**
 * @typedef {Object} TCallerInfo
 * @property {() => string} toString
 * @property {string} str Caller error stack line.
 * @property {string} file Caller file path.
 * @property {number} line Caller line.
 * @property {number} col Caller column.
 * @property {Error} error Caller error stack instance.
 */

/**
 * @returns {TCallerInfo | null}
 */
function getCallerLine() {
  const err = new Error();
  const stack = err.stack || '';
  const callerLine = stack.split(/\n\s*at\s+/g);

  if (callerLine.length >= 2) {
    const str = callerLine[3];
    const [file, line, col] = str
      .replace(/^\s*at\s+/, '')
      .replace(/^(.*):(\d+):(\d+)$/, '$1|$2|$3')
      .split(/\|/g);

    const o = {
      toString: () => str,

      get str() {
        return str;
      },

      get file() {
        return file;
      },

      get line() {
        return parseInt(line);
      },

      get col() {
        return parseInt(col);
      },

      get error() {
        return err;
      },
    };

    return o;
  } else {
    return null;
  }
}

使用方法:

function foo() {
  console.info(getCallerLine());
}

foo(); // Prints this line as Caller Line details.

3
据我所知,在Node.js中打印完整的堆栈跟踪是不可能的,你只能打印“部分”堆栈跟踪,你看不到代码从哪里来,只能看到异常发生的位置。这就是Ryan Dahl在这个YouTube视频中解释的。http://youtu.be/jo_B4LTHi3I ,具体时间是56:30。希望这可以帮助到你。

2
真的,但是@Timboudreau答案中的模块“修复”了这个问题。 - Bogdan D

3

如果还有人像我一样在寻找这个功能,那么我们可以使用一个叫做 "stack-trace" 的模块。它非常流行。 NPM链接

然后沿着调用栈走一遍。

  var stackTrace = require('stack-trace');
  .
  .
  .
  var trace = stackTrace.get();
  trace.map(function (item){ 
    console.log(new Date().toUTCString() + ' : ' +  item.toString() );  
  });

或者只需打印跟踪:

var stackTrace = require('stack-trace');
.
.
.
var trace = stackTrace.get();
trace.toString();

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