Erkennen Sie, ob Sie über erforderlich oder direkt über die Befehlszeile aufgerufen werden

Antworten:

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

Die Dokumentation hierzu finden Sie hier: https://nodejs.org/docs/latest/api/modules.html#modules_accessing_the_main_module

nicolaskruchten
quelle
3
Gibt es eine Möglichkeit, dies zu umgehen? Ich habe Code (über den ich keine Kontrolle habe), der dies tut, aber ich muss ihn benötigen () und ihn so verhalten lassen, als ob er direkt aufgerufen wurde. Grundsätzlich muss ich etwas täuschen, das diesen Test verwendet, um zu glauben, dass er direkt aufgerufen wurde.
Kevin
2
@ Kevin Ich weiß nicht, wie man das macht require(), aber Sie könnten es vielleicht tun, indem Sie entweder die Datei importieren und dann darauf laufen evallassen oder indem Sierequire('child_process').exec('node the_file.js')
MalcolmOcean
Wenn Sie ES-Module mit Node.js verwenden, können Sie mit dem es-mainPaket überprüfen, ob ein Modul direkt ausgeführt wurde.
Tim Schaub
91

Es gibt einen anderen, etwas kürzeren Weg (in den genannten Dokumenten nicht beschrieben).

var runningAsScript = !module.parent;

In diesem Blog-Beitrag habe ich weitere Details dazu beschrieben, wie dies alles unter der Haube funktioniert .

Thorsten Lorenz
quelle
+1, das gefällt mir besser, aber ich werde zögern, bevor ich akzeptierte Antworten wechsle. :)
Bryan Field
8
Wie ich bereits sagte, ist der offizielle Weg, der dokumentiert wird, der beschriebene @nicolaskruchten. Dies ist nur eine Alternative, es ist nicht erforderlich, die akzeptierte Antwort zu wechseln. Beide arbeiten.
Thorsten Lorenz
10
Ich musste dies eher als den dokumentierten Weg verwenden - der dokumentierte Weg funktioniert z. node script.jsaber nicht cat script.js | node. Dieser Weg funktioniert für beide.
Tim Malone
9

Ich war ein wenig verwirrt von der Terminologie, die in den Erklärungen verwendet wurde. Also musste ich ein paar schnelle Tests machen.

Ich fand heraus, dass diese die gleichen Ergebnisse liefern:

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

Und für die anderen verwirrten Menschen (und um die Frage direkt zu beantworten):

var isCLI = require.main === module;
var wasRequired = !isCLI;
Bob
quelle
5

Genau wie in Python versuche ich mich immer daran zu erinnern, wie man dieses verdammte Code-Snippet schreibt. Also habe ich beschlossen, ein einfaches Modul dafür zu erstellen. Die Entwicklung hat ein wenig gedauert, da der Zugriff auf die Modulinformationen des Anrufers nicht einfach ist, aber es hat Spaß gemacht zu sehen, wie dies getan werden kann.

Die Idee ist also, ein Modul aufzurufen und zu fragen, ob das Anrufermodul das Hauptmodul ist. Wir müssen das Modul der Aufruferfunktion herausfinden. Mein erster Ansatz war eine Variation der akzeptierten Antwort:

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

Aber das funktioniert garantiert nicht. module.parentzeigt auf das Modul, das uns in den Speicher geladen hat, nicht auf das, das uns anruft. Wenn es das Anrufermodul war, das dieses Hilfsmodul in den Speicher geladen hat, ist das in Ordnung. Aber wenn nicht, sind wir hilflos. Also müssen wir etwas anderes ausprobieren. Meine Lösung bestand darin, einen Stack-Trace zu generieren und den Modulnamen des Aufrufers von dort abzurufen:

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

Jetzt können wir tun:

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

Oder besser lesbar:

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

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

Unmöglich zu vergessen :-)

Lucio Paiva
quelle
2
Sehr cool. Ich liebe es, wenn gängige Codefragmente mit einem einzigen Namen abgekürzt werden. Kleine Anpassung:return require.main /*this is undefined if we started node interactively*/ && require.main.filename === callerModuleName;
Masterxilo
4

Versuchen Sie dies, wenn Sie ES6-Module verwenden:

if (process.mainModule.filename === __filename) {
  console.log('running as main module')
}
Kebot
quelle
2
Mist, mein process.mainModuleistundefined
datdinhquoc
1
GHOSHHHH, ich muss dies in meiner .mjs-Datei überprüfen
datdinhquoc