【问题标题】:Which file called a class哪个文件称为类
【发布时间】:2021-05-12 06:35:10
【问题描述】:

我想知道哪个文件调用了这个类:

database.ts

class Database {
    constructor() {
        console.log(`This class was called by ${super()}`);
    }
}

server.ts

import Database from 'database.ts';
new Database(); // The constructor would print "This class was called by server.ts"

当然,我使用“super()”呈现的方式是行不通的,但是哪种方式行得通呢?我找不到这个问题的答案。有可能做这样的事情吗?

【问题讨论】:

  • 您首先需要此类信息是值得怀疑的。做什么的?特别是 Javascript 经常被打包用于部署,这在一定程度上删除了有关“文件”的任何信息,所以……
  • 我正在使用 mongo db,我正在使用一个包含其他文件的 utils 文件夹,并且在这个文件中我有一个 database.ts。我从许多不同的文件中调用数据库类,有些文件由于某种原因无法连接。我需要知道哪些。
  • 数据库类不应该连接或不连接基于它被“调用”的“文件”......这些“文件”是否在不同的进程或机器中运行,这会对连接到数据库产生影响?或者这些文件是否将不同的参数传递给导致它以不同方式连接的类?
  • 在注册文件中它传递一些信息来为注册收集集群。在登录文件中,它传递登录信息以收集到集合中,具有此类凭据的用户
  • 您是否希望在服务器端设置错误日志记录?虽然这种方法看起来很奇怪

标签: javascript typescript class oop


【解决方案1】:

记录超类名称

您可以像这样记录超类的名称:

Object.getPrototypeOf(Object.getPrototypeOf(foo)).constructor.name;

https://stackoverflow.com/a/44251889/675721

但是,记录超类名称不会显示调用的文件实例化了你的类。

记录调用文件

为此,您应该创建一个错误日志。

class Database {
    constructor() {
        const a = new Error();
        console.log(a);
    }
}

这将为您提供包含所有文件名的堆栈跟踪。

Error
    at REPL39:1:23
    at Script.runInThisContext (vm.js:132:18)
    at REPLServer.defaultEval (repl.js:479:29)
    at bound (domain.js:430:14)
    at REPLServer.runBound [as eval] (domain.js:443:12)
    at REPLServer.onLine (repl.js:809:10)
    at REPLServer.emit (events.js:326:22)
    at REPLServer.EventEmitter.emit (domain.js:486:12)
    at REPLServer.Interface._onLine (readline.js:337:10)
    at REPLServer.Interface._line (readline.js:666:8)

调试器

这两种方法都不是最好的方法 - 当类被实例化或数据库不工作时,您应该使用调试器设置断点并环顾四周,看看有什么不同。

【讨论】:

  • 我的意思是,这不是解决它的最漂亮的方法,但它确实解决了我的调试问题。我要更改的一件事是尝试创建一个自定义错误,以查看我是否可以获得文件的更多详细信息。
  • 如果你真的想深入研究这个,有一些库可以让堆栈跟踪分析更容易,比如stacktracejs.com。但是,我认为调试是解决问题症结的最佳方法。根据经验,我知道到处调试数据库连接真的不好玩。祝你好运!
【解决方案2】:

严格来说,这不是一个打字稿问题。没有简单的方法可以做到这一点,但您可以使用我相信的堆栈跟踪来破解。通过这种方式,即使您的应用程序已打包并且文件名信息丢失,您也可以找到您的类在何处被实例化。可以通过处理构造函数参数的被调用者属性来获得堆栈跟踪。例如。请参阅此question 以获取可能的解决方案。即

function stacktrace() { 
  function st2(f) {
    return !f ? [] : 
        st2(f.caller).concat([f.toString().split('(')[0].substring(9) + '(' + f.arguments.join(',') + ')']);
  }
  return st2(arguments.callee.caller);
}

但是您可以制作您自己的此函数版本,将堆栈作为数组返回。我从有关问题的 cmets 中假设您希望将调用者存储在类中并在出现错误时将其记录下来,因此将跟踪存储为对象可能更适合您的需求。

然后从 Database 类的构造函数中调用这个函数。

【讨论】:

  • 它确实很有意义,但在我的使用中,我只会用来制作调试部分,因为它不会出现在项目的最终工作版本中。有没有更简单的方法 ?我的意思是,我还没有打包的应用程序
  • 我假设您使用的是 node.js。在那里你可以得到当前文件名require('path').basename(__filename);,但它只会返回当前文件名。当您的数据库类被实例化时,您可以将其传递给您的构造函数。但是,对于 IMO 的调试目的来说,这将是一种过度杀伤力。
  • 实际上你的思路很有趣——查看module.parent会告诉你require()是哪个文件,但只是第一次需要它,所以没那么有用(此属性也已弃用)
【解决方案3】:

当然,我可以在构造函数中添加一个参数。但是还有其他方法吗?

class Database() {
    constructor(fileLocation: string) {
        console.log(`This file was called by ${fileLocation}`);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-03
    • 1970-01-01
    • 1970-01-01
    • 2010-12-31
    • 1970-01-01
    • 2011-12-23
    • 1970-01-01
    • 2019-07-15
    相关资源
    最近更新 更多