Узел.JS: обнаружение, если вызывается через require или непосредственно с помощью командной строки
Как я могу определить, является ли мой узел.JS файл был вызван с помощью SH:node path-to-file
или JS:require('path-to-file')
?
это узел.JS эквивалентен моему предыдущему вопросу в Perl: как я могу запустить свой скрипт Perl, только если он не был загружен require?
4 ответа:
if (require.main === module) { console.log('called directly'); } else { console.log('required as a module'); }
смотрите документацию для этого здесь: https://nodejs.org/docs/latest/api/all.html#modules_accessing_the_main_module
есть еще один, немного более короткий путь (не описанный в упомянутых документах).
var runningAsScript = !module.parent;
Я изложил более детально о том, как это все работает под капотом в этот блог.
Я был немного смущен терминологией, используемой в объяснении (Ях). Так что мне пришлось сделать пару быстрых тестов.
я обнаружил, что они дают те же результаты:
var isCLI = !module.parent; var isCLI = require.main === module;
а для других растерянных людей (и чтобы ответить на вопрос напрямую):
var isCLI = require.main === module; var wasRequired = !isCLI;
как и в 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 }
невозможно забыть :-)