Javascript Nodejs:获取调用方函数的文件名

Javascript Nodejs:获取调用方函数的文件名,javascript,node.js,Javascript,Node.js,我想知道如何获得函数调用方的绝对路径 可以这样说: 在文件a.js中,我调用b()b()是在文件b.js中定义的函数a.js需要b。那么如何从节点中的b.js获取a.js绝对路径呢?在JavaScript中获取堆栈跟踪非常困难。我发现的最好的方法是抛出一个错误,捕捉它,从Error.getStack()(并非在所有浏览器中都实现,这意味着您需要IE)获取堆栈并格式化输出 每个堆栈帧为您提供一个文件路径、行号和函数名。Webkit甚至支持参数,但我上次检查时,它还不起作用 然后是跨不同事件跟踪代码

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

可以这样说:


在文件
a.js
中,我调用
b()
b()
是在文件
b.js
中定义的函数
a.js
需要
b
。那么如何从节点中的
b.js
获取
a.js
绝对路径呢?

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

每个堆栈帧为您提供一个文件路径、行号和函数名。Webkit甚至支持参数,但我上次检查时,它还不起作用

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


实际上,我写了一篇关于此的博文:

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

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

//or

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

这是一个如何使用stacktrace在节点中查找调用方文件的示例

function _getCallerFile() {
    try {
        var err = new Error();
        var callerfile;
        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) return callerfile;
        }
    } catch (err) {}
    return undefined;
}

这里不完全回答这个问题 但有些人可能会感激这些信息

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

process.mainModule.filename
没有尝试过很多用途™ 不过


这似乎是一个相当不错的解释:。

无法恢复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;
}
npm有一个返回调用者路径和文件名的函数。

使用


如果你使用第一个答案,你可能会和其他试图做同样事情的图书馆搞砸。例如,请参见:

如果在实现调用方文件的文件中没有调用所需的函数,则可以编写:

函数_getCallerFile()
{
const prepareStackTraceOrg=Error.prepareStackTrace;
const err=新错误();
Error.prepareStackTrace=(\uuz,堆栈)=>stack;
常量堆栈=err.stack;
Error.prepareStackTrace=prepareStackTraceOrg;
返回堆栈[1]。getFileName();
}
try…catch
是不必要的,因为如果将
错误
赋给变量,则不会抛出该错误

此外,如果要在多个项目中使用
\u getCallerFile
,您可能希望将其放入自己的文件中,但随后,您将获得调用
\u getCallerFile
的文件的名称。 在这种情况下,只需编写
返回堆栈[2].getFileName(),i。E在调用堆栈中再后退一步

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

仅供参考:
NodeJS.CallSite
还有更多有趣的方法,例如。g<代码>获取函数名

更新

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

函数_getCallerFile()
{
const err=新错误();
Error.prepareStackTrace=(\uuz,堆栈)=>stack;
常量堆栈=err.stack;
Error.prepareStackTrace=未定义;
返回堆栈[1]。getFileName();
}

try{throw new Error();}catch(e){console.log(JSON.stringify(e));}在NodeJSY上不起作用您无法对本机对象进行JSON编码。你为什么要这么做请看我的答案。肯定没有回答这个问题,但这对我有帮助。谢谢伟大的我花了几个小时试图解决一个与此相关的问题。重新分配原始函数修复了所有问题。您好,此解决方案运行良好。。。但是,如果在回调中调用了函数,那么它将获得触发回调的文件的名称。调用方并不总是预先确定的,因此:这种方式将不适用于合并路径或遍历路径。查找调用者的补丁是不同的。调用者包在调试时返回internal/module.js。github上发布的示例也返回与节点v8.11.1上调用者相同的“internal/module.js”。这是一个很好的答案。