首页 > 解决方案 > TS/Node.js:获取类实例的绝对路径而不是类本身

问题描述

有没有办法在不将其传递给构造函数的情况下获取创建类实例的文件的路径(__dirname)?例如,

// src/classes/A.ts
export class A {
    private instanceDirname: string;
    constructor() {
        this.instanceDirname = ??
    }
}

// src/index.ts
import { A } from "./classes/A"
const a = new A();
// a.instanceDirname === __dirname ✓

我尝试了 callsite,它起作用了,但我不得不做一些我不满意的正则表达式来获得我需要的东西,我还尝试了一个名为caller-callsite的模块,但最终返回的是模块路径,而不是路径创建实例的文件。有解决方法吗?

标签: node.jstypescript

解决方案


我会让呼叫者传递位置信息。嗅这些东西对我来说似乎是一种代码味道(请原谅双关语)。;-)

但是您可以通过在实例的 V8 调用堆栈上使用正则表达式来做到这一点Error,但它仍然涉及执行正则表达式(您不喜欢使用 callsite),尽管它是在 V8 自己的堆栈上执行它们,而不是可能会以一种破坏性的方式发生变化(当然不会,除非你升级 Node.js,所以它很容易测试)。看评论:

// A regular expression to look for lines in this file (A.ts / A.js)
const rexThisFile = /\bA\.[tj]s:/i;

// Your class
export class A {
    constructor() {
        // Get a stack trace, break into lines -- this is V8, we can rely on the format
        const stackLines = (new Error().stack).split(/\r\n|\r|\n/);
        // Find the first line that doesn't reference this file
        const line = stackLines.find((line, index) => index > 0 && !rexThisFile.test(line));
        if (line) {
            // Found it, extract the directory from it
            const instanceOfDirName = line.replace(/^\s*at\s*/, "")
                         .replace(/\w+\.[tj]s[:\d]+$/, "")
                         .replace(/^file:\/\//, "");
            console.log(`instanceOfDirName = "${instanceOfDirName}"`);
        }
    }
}

这三个替换可以组合:

const instanceOfDirName = line.replace(/(?:^\s*at\s*(?:file:\/\/)?)|(?:\w+\.[tj]s[:\d]+$)/g, "");

...但为了清楚起见,我将它们分开了;不会对性能产生任何影响。


推荐阅读