我想知道如何获取调用函数的绝对路径?
假设:
在文件a.js
中,我调用了b()
函数;b()
函数定义在b.js
文件中。 a.js
需要b
。那么,在Node中,如何从b.js
获取a.js
的绝对路径?
我想知道如何获取调用函数的绝对路径?
假设:
在文件a.js
中,我调用了b()
函数;b()
函数定义在b.js
文件中。 a.js
需要b
。那么,在Node中,如何从b.js
获取a.js
的绝对路径?
无法恢复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
会更安全,不是吗? - Christoph Thiede这是一个示例,展示如何使用 stacktrace 在 Node 中查找调用者文件
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;
}
process.mainModule.filename
虽然没有尝试过太多使用方法™。
这似乎是一个相当不错的解释:https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi。
如果您在实现函数的文件中未调用需要调用者文件的函数(如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
。
更新
我注意到在分配 lambda 前 Error.prepareStackTrace === undefined
。如果你不相信我,只需将 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();
}
使用https://github.com/sindresorhus/callsites
如果您使用第一个答案,可能会与其他试图做同样事情的库混淆。例如,请参见:https://github.com/facebook/jest/issues/5303
npm包caller package中有一个函数,返回调用者的路径和文件名。
Error.getStack()
(并非所有浏览器都实现了,这意味着您的IE可能不支持)中获取堆栈,并格式化输出。require.resolve(module)
来确定模块的完整路径:var path = require.resolve("a");
//or
var path = require.resolve("./a.js");
console.log((new Error()).stack.split("\n")[1].split("/").slice(-1)[0].split(":")[0]) // "caller_file_name.js"
- marcelosalloum