Detect if called through require or directly by command line

隐身守侯 提交于 2019-11-27 04:56:37

问题


How can I detect whether my Node.JS file was called using SH:node path-to-file or JS:require('path-to-file')?

This is the Node.JS equivalent to my previous question in Perl: How can I run my Perl script only if it wasn't loaded with require?


回答1:


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

See documentation for this here: https://nodejs.org/docs/latest/api/modules.html#modules_accessing_the_main_module




回答2:


There is another, slightly shorter way (not outlined in the mentioned docs).

var runningAsScript = !module.parent;

I outlined more details about how this all works under the hood in this blog post.




回答3:


I was a little confused by the terminology used in the explanation(s). So I had to do a couple quick tests.

I found that these produce the same results:

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

And for the other confused people (and to answer the question directly):

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



回答4:


Try this if you are using ES6 modules:

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



回答5:


Just like in Python, I always find myself trying to remember how to write this goddamn code snippet. So I decided to create a simple module for it. It took me a bit to develop since accessing caller's module information isn't straighforward, but it was fun to see how it could be done.

So the idea is to call a module and ask it if the caller module is the main one. We have to figure out the module of the caller function. My first approach was a variation of the accepted answer:

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

But that is not guaranteed to work. module.parent points to the module which loaded us into memory, not the one calling us. If it was the caller module which loaded this helper module into memory, that's fine. But if it wasn't, we're helpless. So we need to try something else. My solution was to generate a stack trace and get the caller's module name from there:

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;
};

Now we can do:

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

Or more readable:

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

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

Impossible to forget :-)



来源:https://stackoverflow.com/questions/6398196/detect-if-called-through-require-or-directly-by-command-line

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!