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


Answers:


471
if (require.main === module) {
    console.log('called directly');
} else {
    console.log('required as a module');
}

请在此处查看相关文档:https : //nodejs.org/docs/latest/api/modules.html#modules_accessing_the_main_module


3
有什么办法可以解决这个问题?我有执行此操作的代码(我没有控制权),但是我需要require()它并使它像直接调用一样起作用。基本上,我需要愚弄使用该测试的某些东西,以为直接调用了该测试。
凯文

2
@Kevin我不知道如何使用require(),但是您可以通过导入文件然后eval在其上运行或通过运行require('child_process').exec('node the_file.js')
MalcolmOcean

将ES模块与Node.js一起使用时,可以使用该es-main包检查模块是否直接运行。
Tim Schaub

91

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

var runningAsScript = !module.parent;

我在此博客文章中概述了所有这些工作原理的更多细节。


+1,我会更喜欢这个,但是在切换可接受的答案之前我会犹豫。:)
Bryan Field

8
正如我所指出的,记录的正式方式是概述的@nicolaskruchten。这只是一种选择,无需切换已接受的答案。两者都可以。
Thorsten Lorenz

10
我不得不使用这种方式,而不是使用记录的方式-例如,记录的方式适用。node script.js但是不是cat script.js | node。这种方式对两者都适用。
Tim Malone

9

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

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

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

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

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

5

就像在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
}

不可能忘记 :-)


2
很酷。当通用代码段缩写为单个名称时,我会喜欢它。小调整:return require.main /*this is undefined if we started node interactively*/ && require.main.filename === callerModuleName;
masterxilo

4

如果使用的是ES6模块,请尝试以下操作:

if (process.mainModule.filename === __filename) {
  console.log('running as main module')
}

2
废话,我process.mainModuleundefined
daddinhquoc

1
GHOSHHHH,我需要在我的.mjs文件中进行检查
daddinhquoc 18-10-17
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.