402 Stimmen

Erkennen, ob der Aufruf über require oder direkt über die Befehlszeile erfolgt

Wie kann ich feststellen, ob meine Node.JS-Datei mit SH aufgerufen wurde: node path-to-file oder JS: require('path-to-file') ?

Dies ist das Node.JS-Äquivalent zu meiner vorherigen Frage in Perl: Wie kann ich mein Perl-Skript nur ausführen, wenn es nicht mit require geladen wurde?

630voto

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

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

109voto

Thorsten Lorenz Punkte 11563

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

var runningAsScript = !module.parent;

Weitere Einzelheiten darüber, wie das alles unter der Haube funktioniert, habe ich in dieser Blogbeitrag .

35voto

seanCodes Punkte 423

Für diejenigen, die ES-Module (und Node 10.12+) verwenden, können Sie import.meta.url :

import path from 'path';
import { fileURLToPath } from 'url'

const nodePath = path.resolve(process.argv[1]);
const modulePath = path.resolve(fileURLToPath(import.meta.url))
const isRunningDirectlyViaCLI = nodePath === modulePath

Dinge wie require.main , module.parent y __dirname / __filename nicht in ESM verfügbar sind .

Note : Wenn Sie ESLint verwenden, kann es sein, dass es an dieser Syntax scheitert; in diesem Fall müssen Sie Update für ESLint ^7.2.0 und drehen Sie Ihr ecmaVersion bis zu 11 ( 2020 ).

_Mehr Informationen: process.argv , import.meta.url_

14voto

bob Punkte 6781

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

Ich habe festgestellt, dass diese zu den gleichen Ergebnissen führen:

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

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

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

8voto

Lucio Paiva Punkte 15969

Da ich immer wieder versuche, mich daran zu erinnern, wie man dieses verdammte Codeschnipsel schreibt, habe ich beschlossen, ein einfaches Modul dafür zu erstellen. Es hat ein bisschen gedauert, bis es funktionierte, da der Zugriff auf die Modulinformationen des Aufrufers nicht einfach ist, aber es hat Spaß gemacht, zu sehen, wie es gemacht werden kann.

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

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

Aber das ist keine Garantie für einen Erfolg. module.parent zeigt auf das Modul, das geladen uns in die Erinnerung, nicht derjenige, der uns ruft. Wenn es das aufrufende Modul ist, das dieses Hilfsmodul in den Speicher geladen hat, ist alles in Ordnung. Aber wenn nicht, wird es nicht funktionieren. Wir müssen also etwas anderes versuchen. Meine Lösung bestand darin, einen Stack-Trace zu erstellen und daraus den Namen des aufrufenden Moduls zu ermitteln:

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

Speichern Sie dies als is-main-module.js und jetzt können Sie es tun:

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

if (isMainModule()) {
    console.info("called directly");
} else {
    console.info("required as a module");
}

Das ist leichter zu merken.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X