2013-10-17 12 views
5

nodejsの[my_func_name]ウィンドウに相当するものは何ですか?私はstdinから文字列を読み込みます。関数名であれば実行したいと思います。私はグローバル[my_func_name]は動作するかもしれないと思ったが、残念ながらそれはしない。nodejsの文字列から関数を呼び出す

答えて

12

はそれだけで正常に動作

global.foo = function foo() { 
    console.log("foo was called"); 
} 

process.stdin.on("data", function(input) { 

    // don't forget to call .trim() to remove the \n 
    var fn = input.toString().trim(); 

    // function exists 
    if (fn in global && typeof global[fn] === "function") { 
    global[fn](); 
    } 

    // function does not exist 
    else { 
    console.log("could not find " + fn + " function"); 
    } 
}); 

process.stdin.resume(); 

これは良いアイデアであるか否かは、出力

foo 
foo was called 
bar 
could not find bar function 

...がよく、それは全く別の議論です。


EDIT —≈18ヶ月後...うん、それはそのようなグローバル関数を呼び出す恐ろしい勧めします。

ここでは、の1つです。あなたはもっと良い方法で問題に近づけることができます。以下では少しREPL(read-eval-printループ)を作成します。それをよりよく理解するために、私はそれをいくつかの部分に分解します。

最初に、コマンドを実行する前にREPLがユーザーがEnterキーを押すのを待っていることを確認します。そのためには、パイプ、以下のコードはES6を使用して書かれて

ダウンlineを送信する前に"\n"文字を待っtransform streamを作成します。コードを実行するための互換性のある環境が見つからない場合は、babelをチェックアウトすることをおすすめします。あなたが処理をストリーミングする新しいしていると、それは非常に意味がない場合

// line-unitizer.js 
import {Transform} from 'stream'; 

class LineUnitizer extends Transform { 
    constructor(delimiter="\n") { 
    super(); 
    this.buffer = ""; 
    this.delimiter = delimiter; 
    } 
    _transform(chunk, enc, done) { 
    this.buffer += chunk.toString(); 
    var lines = this.buffer.split(this.delimiter); 
    this.buffer = lines.pop(); 
    lines.forEach(line => this.push(line)); 
    done(); 
    } 
} 

export default LineUnitizer; 

LineUnitizerにハングアップを取得しないでください。この種のストリーム変換は非常に一般的です。一般的な考え方は次のとおりです。process.stdinを受信ストリームにパイプすると、ユーザーがキーを押すたびにprocess.stdinがデータを発信します。ただし、Repl(下記に実装)は、ユーザがが完了してコマンドを入力するまでコマンドを実行することができません。LineUnitizerは、ユーザがenterを押して(ストリームに"\n"を挿入する)待機してから、_transformにコマンドが処理のためにreplに送信される準備ができていることを通知する部分です。

さんは今

// repl.js 
import {Writable} from 'stream'; 

class Repl extends Writable { 
    _parse(line) { 
    var [cmd, ...args] = line.split(/\s+/); 
    return {cmd, args}; 
    } 
    _write(line, enc, done) { 
    var {cmd, args} = this._parse(line.toString()); 
    this.emit(cmd, args); 
    done(); 
    } 
} 

export default Repl; 

まあReplを見てみましょう。ちょっと、それは簡単でした!それは何ですか? replは、行を受け取るたびに、いくつかの引数を含むイベントを送出します。ここでは、視覚的な方法は、今、コマンドが

The user enters  emit event  args 
------------------------------------------------------------- 
add 1 2 3    "add"   ["1", "2", "3"] 
hens chocobo cucco "hens"   ["chocobo", "cucco"] 
yay     "yay"   [] 

がOK解析される方法を見るのは、それが動作確認するために一緒にすべてを配線できるようにするのです

// start.js 
import LineUnitizer from './line-unitizer'; 
import Repl   from './repl'; 

process.stdin 
    .pipe(new LineUnitizer()) 
    .pipe(
    (new Repl()) 
     .on("add", function(args) { 
     var sum = args.map(Number).reduce((a,b) => a+b, 0); 
     console.log("add result: %d", sum); 
     }) 
     .on("shout", function(args) { 
     var allcaps = args.map(s => s.toUpperCase()).join(" "); 
     console.log(allcaps); 
     }) 
     .on("exit", function(args) { 
     console.log("kthxbai!"); 
     process.exit(); 
     })); 

を実行し、それ

$ node start.js 

出力

接頭辞の付いた行は>です入力。 >は実際に端末に表示されません。

> add 1 2 3 
add result: 6 
> shout I can see it in your face! 
I CAN SEE IT IN YOUR FACE! 
> exit 
kthxbai! 

あなたはそれは素晴らしいことだと思うならば、私たちもまだ行われていません。このようにプログラムを書くことのメリットは、プログラムにどのように到達するかにかかわらずコマンドに作用できることです。それはかなりfricken素晴らしいですので

は、今、このcommands.txtファイル

add 100 200 
shout streams are the bee's knees 
exit 

を考えてみましょう。この

$ cat commands.txt | node start.js 

出力

300 
STREAMS ARE THE BEE'S KNEES 
kthxbai! 

[OK]を同じように実行します。コマンドがどこから来てもよいと考えてください。データベースイベント、ネットワークを介したもの、CRONジョブなどがあります。すべてがうまく分離されているので、さまざまな入力を簡単に受け入れるようにこのプログラムを簡単に適応させることができます。 が探しされるtests.jsで、この例では

+1

おかげで、あなたは正しいです。私は、ウィンドウオブジェクトの場合のようにグローバル関数が自動的にグローバルオブジェクトに追加されると考えました。それはあなたの問題 – PaulK

+1

はこの答えを受け入れる考える@PaulK、それは価値がある何のために、私は多くの複雑なNode.jsのアプリケーションを書いていると私は決して(さえ*一度*)しかし、 – fardjad

+0

@PaulKが解決するかどうか – naomik

0
var theTests = require('./tests'); 
//@TODO CaseID should be caseId 
var CaseID = 5678; 
// use dynamic functions 
var functionName = 'theTests.TEST_' + CaseID; 
var functionString = String('TEST_' + CaseID); 

var check = eval('typeof ' + functionName); // bad 
if (check == 'function') { 
    // run the function 
    // testResult = eval(functionName); nope 
    testResult = theTests[functionString](); //yep :) 
    console.log(testResult); 
} 
else { 
    console.log('No test functions for ' + CaseID); 
} 

...

TEST_5678: function(){ 
    return some thing; 
}, 
1

別のファイルにあなたの関数を記述し、それらをエクスポートし、それらを呼び出すためにその名を参照して使用し、 functions.js index.jsでで定義されたような

// functions.js 
var funcOne = function(){ 
        console.log('function ONE called') 
       } 
module.exports={ 
    // name_exported : internal_name 
    funcOne : funcOne 
} 

使用機能:

// index.js 
var methods = require('./functions.js') // path to functions.js 
methods['funcOne']() 

OUTPUT:

> node index.js 
> function ONE called 
関連する問題