2011-06-18 16 views
191

Node.JSファイルがSH:node path-to-fileまたはJS:require('path-to-file')を使用して呼び出されたかどうかを検出するにはどうすればよいですか?Node.JS:requireまたは直接コマンドラインから呼び出された場合の検出

これはPerlで私の前の質問と同等のNode.jsです:How can I run my Perl script only if it wasn't loaded with require?

+1

[node.jsの可能な複製は、\ _ \ _ name \ _ \ _ == '\ _ \ _ main \ _ \ _'](http://stackoverflow.com/question/4981891/node-js-equivalent-of-pythons-if-name-main) – GingerPlusPlus

答えて

297
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

+0

Nicolas(そしてJesse)に感謝します –

+2

これを回避する方法はありますか?私はこれを行うコードを持っていますが、それを要求し、直接呼び出されたかのように動作させる必要があります。基本的に、私はそのテストを使って直接呼び出されたと思うようなものをだます必要があります。 – Kevin

+2

@Kevin 'require()'でこれを行うことについてはわかりませんが、ファイルを読み込んで 'eval'を実行するか、' require( 'child_process')を実行することで多分実行できます。 'node the_file.js') ' – MalcolmOcean

58

(言及に概説されていない別の、やや短い方法がありますdocs)。

var runningAsScript = !module.parent;

私はこのすべてがthis blog postにボンネットの下にどのように動作するかについての詳細を概説。

+0

+1、私はこれがより好きですが、私は受け入れられた答えを切り替える前に躊躇します。 :) –

+8

私が指摘したように、文書化されている正式な方法は、概説された@nicolaskruchtenです。これは単なる代替案であり、受け入れられた回答を切り替える必要はありません。どちらも動作します。 –

+1

私は文書化された方法ではなく、これを使用しなければなりませんでした。 'node script.js'ではなく' cat script.js |ノード 'である。この方法は両方の場合に有効です。 –

2

私は、説明で使用される用語で少し混乱しました。だから私はいくつかの簡単なテストをしなければなりませんでした。

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

そして、他の混乱した人々のための

(直接質問に答えるために)::ちょうどPythonでのような

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

を、私はいつも見つける

私は、これらが同じ結果をもたらすことがわかりましたこのコードを書く方法を覚えようとしています。だから私はそれのための簡単なモジュールを作成することにしました。発信者のモジュール情報にアクセスするのは簡単ではありませんでしたので、開発には少し時間がかかりましたが、どのように実行できるかを確認するのは楽しいことでした。

したがって、モジュールを呼び出して、呼び出し側モジュールが主モジュールであるかどうかを確認することです。呼び出し側関数のモジュールを理解する必要があります。私の最初のアプローチは、受け入れられた答えのバリエーションでした:

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 
} 

インポッシブル:-)

+0

非常にクールです。一般的なコードスニペットを単一の名前に省略すると、私はそれが大好きです。小さな調整: 'return require.main/*対話的にノードを開始した場合はこれは未定義です。*/&& require.main.filename === callerModuleName;' – masterxilo

関連する問題