#node.js #typescript
#node.js #typescript
Вопрос:
Есть ли способ получить путь (__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, но в итоге он вернул путь к модулю, а не путь к файлу, в котором был создан экземпляр.
Есть ли обходной путь для этого?
Ответ №1:
Я бы попросил вызывающих абонентов передавать информацию о местоположении. Обнюхивание этого материала кажется мне запахом кода (простите за каламбур). 😉
Но вы можете сделать это, используя регулярные выражения в стеке вызовов версии 8 из Error
экземпляра, но это все равно связано с выполнением регулярных выражений (которые вам не понравились в callsite), хотя они выполняются в собственных стеках версии 8, которые вряд ли изменятся кардинальным образом (и, конечно,не будет, за исключением случаев, когда вы выполняете обновления 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(/rn|r|n/);
// Find the first line that doesn't reference this file
const line = stackLines.find((line, index) => index > 0 amp;amp; !rexThisFile.test(line));
if (line) {
// Found it, extract the directory from it
const instanceOfDirName = line.replace(/^s*ats*/, "")
.replace(/w .[tj]s[:d] $/, "")
.replace(/^file:///, "");
console.log(`instanceOfDirName = "${instanceOfDirName}"`);
}
}
}
Эти три замены могут быть объединены:
const instanceOfDirName = line.replace(/(?:^s*ats*(?:file://)?)|(?:w .[tj]s[:d] $)/g, "");
… но я оставил их отдельно для ясности; не собираюсь заботиться о какой-либо разнице в производительности.
Комментарии:
1. Близко к тому, что я делал с callsite, за исключением того, что в некоторых случаях стек содержал нулевые записи, которые меня раздражали, но я думаю, этого можно было избежать, используя V8 напрямую.. Спасибо 🙂