我试图让 nodejs 与冒险进行互动,这是一款基于旧版本的游戏。我们的想法是将冒险作为一个子进程开放,然后通过写入stdin
并在stdout
上放置一个事件监听器来玩游戏。
当游戏开始时,它会打印一个初始值:
欢迎来到冒险!你想要指示吗?
为了说明我的问题,我有一个nodejs + express实例:
var childProcess = require('child_process');
var spawn = childProcess.spawn;
var child = spawn('adventure');
console.log("spawned: " + child.pid);
child.stdout.on('data', function(data) {
console.log("Child data: " + data);
});
child.on('error', function () {
console.log("Failed to start child.");
});
child.on('close', function (code) {
console.log('Child process exited with code ' + code);
});
child.stdout.on('end', function () {
console.log('Finished collecting data chunks.');
});
但是当我启动服务器时,游戏中的文字并没有到达事件监听器:
spawned: 24250
这是我得到的所有输出。永远不会调用child.stdout.on
偶数监听器。为什么游戏中的初始线没有被选中?
如果我将以下行添加到上面的javascript块中,则会立即显示程序输出。所以adventure
运行,我现在可以强制它触发child.stdout.on
事件监听器...但这也会结束子进程,这会使读取和写入的目的失效。
...
child.stdout.on('end', function () {
console.log('Finished collecting data chunks.');
});
child.stdin.end();
现在输出是:
spawned: 28778
Child data:
Welcome to Adventure!! Would you like instructions?
user closed input stream, quitting...
Finished collecting data chunks.
Child process exited with code 0
我确信这对我来说是一个微不足道的疏忽,我感谢任何帮助解决这个问题。
答案 0 :(得分:4)
经过几次Nodejs文档之后,我确信自己错过了一些非常大的东西,或者spawn
命令无法正常工作。所以我创建了一个github issue。
答案立即发布:如果您想要快速访问,子进程无法缓冲输出。
所以要实现我最初想要的东西:
var childProcess = require('child_process');
var spawn = childProcess.spawn;
var child = spawn('unbuffer', 'adventure');
console.log("spawned: " + child.pid);
child.stdout.on('data', function(data) {
console.log("Child data: " + data);
});
child.on('error', function () {
console.log("Failed to start child.");
});
child.on('close', function (code) {
console.log('Child process exited with code ' + code);
});
child.stdout.on('end', function () {
console.log('Finished collecting data chunks.');
});
功能差异在于使用unbuffer
,这是一个禁用输出缓冲的命令。
答案 1 :(得分:1)
为什么不从游戏中提取第一行?
我在一个从node.js调用C ++程序的项目中遇到了同样的问题。我意识到问题出在编译的C ++程序中:我不是在刷新stdout
流。在打印一行之后添加fflush(stdout);
解决了该问题。希望您仍然可以访问游戏的来源!
答案 2 :(得分:0)
传递的data
是缓冲区类型,而不是字符串。因此,您需要一个解码器来读取该缓冲区,然后进行日志记录。
以下是如何做到的。
var StringDecoder = require('string_decoder').StringDecoder;
var decoder = new StringDecoder('utf8');
child.stdout.on('data', function (data) {
var message = decoder.write(data);
console.log(message.trim());
});