从Node.js中的字符串调用函数 [英] Call function from string in nodejs
问题描述
nodejs中的window [my_func_name]等效于什么?我正在从stdin读取一个字符串,如果它是一个函数名,我想执行它.我以为global [my_func_name]可能有用,但不幸的是,它无效.
What is the equivalent to window[my_func_name] in nodejs? I'm reading a string from stdin and if it's a function name I want to execute it. I thought global[my_func_name] might work but unfortunately it doesn't.
推荐答案
效果很好
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
这是否是个好主意... 那是完全不同的讨论.
Whether or not this is a good idea... well, that's an entirely different discussion.
编辑—大约18个月后...是的,调用这样的全局函数是一个可怕的想法.
EDIT — ≈18 months later... Yeah, it's a horrible idea to call a global function like that.
这就是您可以以一种更好的方式解决问题的一种方法.下面我们将构建一些 REPL REPL (read-eval-print循环).为了更好地理解它,我将其分为几个部分.
In saying that, here's one way you could approach the problem in a much better way. Below we're going to build a little REPL (read-eval-print loop). In order to understand it better, I'll break it down into a couple parts.
首先,我们要确保REPL在尝试运行其命令之前先等待用户按下Enter键.为此,我们将创建一个等待的转换流.\ n"
字符,然后沿管道发送 line
First, we want to make sure our REPL waits for the user to press enter before we try running their command. To do that, we'll create a transform stream that waits for a "\n"
character before sending a line
down the pipe
The code below is written using ES6. If you're having trouble finding a compatible environment to run the code, I suggest you check out 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
进行处理!
Don't get too hung up on LineUnitizer
if you're new to stream processing and it doesn't quite make sense. This kind of stream transform is extremely common. The general idea is this: once we pipe process.stdin
into a receiving stream, process.stdin
will be emitting data every time the user presses a key. However, our Repl
(implemented below) can't act on a command until the user has finished typing the command. LineUnitizer
is the part that waits for the user to press enter (which inserts a "\n"
into the stream) and then signals to _transform
that the command is ready to be sent to repl
for processing!
现在让我们看看 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
接收到一行时,它都会发出带有一些args的事件.这是查看命令解析方式的直观方式
Well hey, that was easy! What does it do tho? Each time repl
receives a line, it emits an event with some args. Here's a visual way to see how a command is parsed
The user enters emit event args
-------------------------------------------------------------
add 1 2 3 "add" ["1", "2", "3"]
hens chocobo cucco "hens" ["chocobo", "cucco"]
yay "yay" []
好吧,现在让我们将所有内容连接在一起以查看其工作原理
Ok, now let's wire everything together to see it work
// 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
输出
以
>
为前缀的行是用户输入.>
实际上不会在您的终端中显示.
Lines prefixed with
>
are user input. The>
will not actually be visible in your terminal.
> add 1 2 3
add result: 6
> shout I can see it in your face!
I CAN SEE IT IN YOUR FACE!
> exit
kthxbai!
如果您认为这很棒,那么我们甚至还没有完成.这样编写程序的好处是,无论命令如何到达我们的程序,我们都可以对其执行操作.
If you think that's awesome, we're not even done yet. The benefits of writing our program this way is that we can act on the commands regardless of how they arrive at our program.
考虑此 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!
好吧,这真是太棒了.现在考虑命令可以来自任何地方.可能是数据库事件,网络上的某些事件,CRON作业等.由于所有内容都很好地分开了,因此我们可以轻松地使此程序适应于轻松接受各种输入的过程.
Ok, so that's pretty fricken great. Now consider that the commands could come from anywhere. Could be a database event, something across the network, a CRON job, etc. Because everything is nicely separated, we could easily adapt this program to accept a variety of inputs with ease.
这篇关于从Node.js中的字符串调用函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!