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

IT技术 javascript node.js
2021-03-02 15:23:01

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

让我们说:

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

6个回答

未能恢复 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;
}
finally用于重置不是更安全Error.prepareStackTrace吗?
2021-04-16 15:23:01
嗨,这个解决方案工作正常......但是如果在回调中调用了一个函数,那么它将获得触发回调的文件的名称
2021-04-18 15:23:01
伟大的!我试图解决与此相关的问题数小时。重新分配原始功能修复了一切。
2021-05-04 15:23:01

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

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;
}
重要的!向下滚动一点,有更新的答案,没有与此相同的潜在错误和陷阱(尽管我确实对其进行了编辑以省略最严重的错误)。@Christoph 似乎是最好的。
2021-04-24 15:23:01

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

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

process.mainModule.filename

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

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

绝对没有回答这个问题,但这对我有帮助。谢谢!
2021-05-15 15:23:01

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

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

如果您需要调用者文件的函数没有在实现它的文件中调用 - 就像在 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被调用的文件的名称在这种情况下,只需 write 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();
}