检测是通过require还是直接通过命令行调用

如何检测是否使用SH:node path-to-file或JS:调用了Node.JS文件require('path-to-file')

这是相当于Perl中我先前的问题的Node.JS:仅在未加载require的情况下才能运行我的Perl脚本?

路易猴子Pro2020/03/19 09:40:39

就像在Python中一样,我总是发现自己想记住如何编写这个该死的代码片段。因此,我决定为其创建一个简单的模块。由于访问调用者的模块信息并不直接,所以花了一些时间进行开发,但是很高兴看到如何实现。

因此,其想法是调用一个模块,并询问调用方模块是否为主要模块。我们必须找出调用者函数的模块。我的第一种方法是对已接受的答案进行修改:

module.exports = function () {
    return require.main === module.parent;
};

但这不能保证有效。module.parent指向将我们加载到内存中的模块,而不是调用我们的模块。如果是调用程序模块将此帮助程序模块加载到内存中,那就很好。但是,如果不是这样,我们将束手无策。因此,我们需要尝试其他方法。我的解决方案是生成堆栈跟踪并从此处获取调用方的模块名称:

module.exports = function () {
    // generate a stack trace
    const stack = (new Error()).stack;
    // the third line refers to our caller
    const stackLine = stack.split("\n")[2];
    // extract the module name from that line
    const callerModuleName = /\((.*):\d+:\d+\)$/.exec(stackLine)[1];

    return require.main.filename === callerModuleName;
};

现在我们可以做:

if (require("./is-main-module")()) {  // notice the `()` at the end
    // do something
} else {
    // do something else
}

或更可读:

const isMainModule = require("./is-main-module");

if (isMainModule()) {
    // do something
} else {
    // do something else
}

不可能忘记 :-)

2020/03/19 09:40:39

我对解释中使用的术语感到有些困惑。所以我不得不做一些快速测试。

我发现它们产生相同的结果:

var isCLI = !module.parent;
var isCLI = require.main === module;

对于其他困惑的人(并直接回答问题):

var isCLI = require.main === module;
var wasRequired = !isCLI;
神无ProHarry2020/03/19 09:40:38

还有另一种较短的方法(在上述文档中未概述)。

var runningAsScript = !module.parent;

这篇博客文章中,我概述了所有这些如何工作的更多细节