33

我想知道如何获得函数调用者的绝对路径?

让我们这么说:

a.js我打电话的文件中b()b()是文件中定义的函数b.jsa.js需要b. 那么如何从节点中获取a.js绝对路径?b.js

4

8 回答 8

50

无法恢复 prepareStackTrace 函数可能会导致问题。这是一个消除副作用的示例

function _getCallerFile() {
    var originalFunc = Error.prepareStackTrace;

    var callerfile;
    try {
        var err = new Error();
        var currentfile;

        Error.prepareStackTrace = function (err, stack) { return stack; };

        currentfile = err.stack.shift().getFileName();

        while (err.stack.length) {
            callerfile = err.stack.shift().getFileName();

            if(currentfile !== callerfile) break;
        }
    } catch (e) {}

    Error.prepareStackTrace = originalFunc; 

    return callerfile;
}
于 2015-04-11T19:01:36.800 回答
33

这是一个如何使用堆栈跟踪在节点中查找调用者文件的示例

function _getCallerFile() {
    var filename;

    var _pst = Error.prepareStackTrace
    Error.prepareStackTrace = function (err, stack) { return stack; };
    try {
        var err = new Error();
        var callerfile;
        var currentfile;

        currentfile = err.stack.shift().getFileName();

        while (err.stack.length) {
            callerfile = err.stack.shift().getFileName();

            if(currentfile !== callerfile) {
                filename = callerfile;
                break;
            }
        }
    } catch (err) {}
    Error.prepareStackTrace = _pst;

    return filename;
}
于 2013-11-05T11:47:29.047 回答
9

这里没有完全回答这个问题,但有些人可能会欣赏这些信息。

使用 NodeJS 和 Forever(-monitor),以下内容包含启动进程的文件名:

process.mainModule.filename

虽然没有尝试过很多用途™。

这似乎是一个相当不错的解释:https ://code.google.com/p/v8/wiki/JavaScriptStackTraceApi 。

于 2014-05-27T13:05:43.053 回答
4

使用https://github.com/sindresorhus/callsites

如果您使用第一个答案,您可能会弄乱其他试图做同样事情的库。参见例如:https ://github.com/facebook/jest/issues/5303

于 2019-03-17T17:25:50.220 回答
4

如果你需要的调用者文件没有​​在实现它的文件中调用——就像在 OP 的场景中一样——你可以写:

function _getCallerFile()
{
    const prepareStackTraceOrg = Error.prepareStackTrace;
    const err = new Error();

    Error.prepareStackTrace = (_, stack) => stack;

    const stack = err.stack;

    Error.prepareStackTrace = prepareStackTraceOrg;

    return stack[1].getFileName();
}

try...catch是不必要的,因为如果Error将其分配给变量,则不会抛出。

此外,如果您想在多个项目中使用它,您可能需要放入_getCallerFile它自己的文件,但是,您将获得_getCallerFile被调用的文件的名称。在这种情况下,只需编写return stack[2].getFileName();,即在调用堆栈中再退一步。

如果你使用 TypeScript,你必须写const stack = err.stack as unknown as NodeJS.CallSite[];,因为Error.stack的声明类型是string,但是我们的prepareStackTrace函数返回一个对象数组NodeJS.CallSite

仅供参考:NodeJS.CallSite还有更多有趣的方法,例如getFunctionName.

更新

我注意到Error.prepareStackTrace === undefined在分配 lambda 之前。如果您不信任我,请添加console.log('prepareStackTraceOrg:', prepareStackTraceOrg);到该功能。因此,我们可以简化函数:

function _getCallerFile()
{
    const err = new Error();

    Error.prepareStackTrace = (_, stack) => stack;

    const stack = err.stack;

    Error.prepareStackTrace = undefined;

    return stack[1].getFileName();
}
于 2021-03-28T15:13:20.137 回答
3

npm caller 包有一个函数可以返回调用者的路径和文件名。

于 2017-12-10T07:17:23.040 回答
1

在 JavaScript 中获取堆栈跟踪非常困难。我发现最好的方法是抛出一个错误,捕获它,从中获取堆栈Error.getStack()(不是在所有浏览器中实现,这意味着你是 IE。)并格式化输出。

每个堆栈帧都会为您提供文件路径、行号和函数名称。Webkit 甚至支持参数,但是当我上次检查时它还没有工作。

然后是跨不同事件跟踪代码的问题。

我实际上写了一篇关于此的博客文章:http: //fritsvancampen.wordpress.com/2013/03/28/error-handling-in-javascript-a-better-way/

于 2013-05-22T17:15:08.820 回答
0

您可以使用require.resolve(module)来确定模块的完整路径:

var path = require.resolve("a");

//or

var path = require.resolve("./a.js");
于 2013-05-22T17:38:19.450 回答