70

如何获得调用当前函数的函数的名称和行?我想要一个像这样的基本调试功能(使用npmlog定义log.debug):

function debug() {
  var callee, line;
  /* MAGIC */
  log.debug(callee + ":" + line, arguments)
}

当从另一个函数调用时,它会是这样的:

function hello() {
   debug("world!")
}
// outputs something like:
// "hello:2 'world!'"

为了清楚起见,我想要的基本上类似于Python 中的这个

import inspect
def caller():
    return inspect.stack()[2][3]
// line no from getframeinfo().lineno

是否有等效的节点来完成此操作?

4

6 回答 6

91

使用此处的信息:在 V8 JavaScript (Chrome & Node.js) 中访问行号

您可以添加一些原型以提供从 V8 访问此信息的权限:

Object.defineProperty(global, '__stack', {
get: function() {
        var orig = Error.prepareStackTrace;
        Error.prepareStackTrace = function(_, stack) {
            return stack;
        };
        var err = new Error;
        Error.captureStackTrace(err, arguments.callee);
        var stack = err.stack;
        Error.prepareStackTrace = orig;
        return stack;
    }
});

Object.defineProperty(global, '__line', {
get: function() {
        return __stack[1].getLineNumber();
    }
});

Object.defineProperty(global, '__function', {
get: function() {
        return __stack[1].getFunctionName();
    }
});

function foo() {
    console.log(__line);
    console.log(__function);
}

foo()

分别返回“28”和“foo”。

于 2013-01-05T14:38:26.457 回答
28

以下代码仅使用核心元素。它从错误实例中解析堆栈。

"use strict";
function debugLine(message) {
    let e = new Error();
    let frame = e.stack.split("\n")[2]; // change to 3 for grandparent func
    let lineNumber = frame.split(":").reverse()[1];
    let functionName = frame.split(" ")[5];
    return functionName + ":" + lineNumber + " " + message;
}
function myCallingFunction() {
    console.log(debugLine("error_message"));
}
myCallingFunction();

它输出类似myCallingFunction:10 error_message

我已将错误的元素提取为变量(lineNumber、functionName),因此您可以按任何方式格式化返回值。

附带说明:该use strict;语句是可选的,只有在您的整个代码都使用严格标准时才能使用。如果您的代码与该代码不兼容(尽管应该兼容),请随意删除它。

于 2018-11-16T14:08:09.687 回答
18

我也有类似的要求。我使用了nodejs提供的Error类的stack属性。
我还在学习节点,所以可能会有错误的机会。

以下是相同的解释。还为此创建了 npm 模块,如果您愿意,可以查看:
1. npm module 'logat'
2. git repo

假设我们使用方法 'log' 'logger' 对象

var logger = {
 log: log
}
function log(msg){
  let logLineDetails = ((new Error().stack).split("at ")[3]).trim();
  console.log('DEBUG', new Date().toUTCString(), logLineDetails, msg);
}

例子:

//suppose file name: /home/vikash/example/age.js
function getAge(age) {
    logger.log('Inside getAge function');    //suppose line no: 9
}

上述示例的输出:

    DEBUG on Sat, 24 Sept 2016 12:12:10 GMT at getAge(/home/vikash/example/age.js:9:12)
    Inside getAge function
于 2016-09-25T07:12:25.950 回答
13

我找到并安装了node-stack-trace模块(用 安装npm install stack-trace),然后定义echo为:

function echo() {
  var args, file, frame, line, method;
  args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];

  frame = stackTrace.get()[1];
  file = path.basename(frame.getFileName());
  line = frame.getLineNumber();
  method = frame.getFunctionName();

  args.unshift("" + file + ":" + line + " in " + method + "()");
  return log.info.apply(log, args); // changed 'debug' to canonical npmlog 'info'
};
于 2013-01-05T14:37:59.920 回答
10

这是用于快速调试目的的单行代码:

console.log("DEBUG", (new Error().stack.split("at ")[1]).trim());

这将使用 Node.js 记录如下内容:

调试 SomeObject.function (/path/to/the/code.js:152:37) 

--

您还可以在末尾添加自定义参数,例如

console.log("DEBUG", (new Error().stack.split("at ")[1]).trim(), ">>>", myVar);

请注意,如果您将其放入辅助函数中,请将堆栈索引从 eg 调整[1][2]

于 2020-04-24T21:43:20.217 回答
1

这是发生错误时获取文件名的一种方法。您必须将函数包装在 onErrorReturnFileName 中。在这里,我func()otherNode文件中包装。

const {func} = require('./otherNode')

function onErrorReturnFileName(funcToRead) {
    let defaultPrepareStackTrace = Error.prepareStackTrace
    try {
        let getStack = function (err, stack) { return stack; };
        Error.prepareStackTrace = getStack
        return {result: funcToRead(), name: null}
    }catch (ex) {
        return {name: ex.stack.shift().getFileName(), result: null}
    }
    Error.preppareStackTrace = defaultPrepareStackTrace
}
console.log(onErrorReturnFileName(func))
于 2021-05-25T17:59:54.737 回答