我试图为使用Node.js的readline模块的CLI编写测试来打印和捕获用户的信息,我似乎无法从stdout捕获任何内容。我面临的问题的一个简单版本如下。
app.js:
#!/usr/bin/env node
const readline = require('readline')
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
})
rl.write('hello\n')
process.exit()
runner.js:
const spawn = require('child_process').spawn
const rl = spawn(__dirname + '/app.js')
rl.stdout.on('data', chunk => {
console.log('stdout says', chunk.toString())
})
运行runner.js
,我希望看到输出stdout says hello
,但没有打印出来。
但是,如果我直接运行app.js
,hello
会打印到控制台。另外,如果我使用其他readline方法,例如question
,处理程序将使用预期数据触发。
为什么这段代码没有按预期工作?如何改变工作?
答案 0 :(得分:2)
与Readline output to file Node.js
相关要捕获rl.write()的输出,一个解决方案是:define" terminal"在创建readline接口实例时为true。
示例代码:
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: true
});
说明: node.js中的readline模块只将数据写入"输出"当"终端"是真的。否则,它只会发出" line" event,并将数据发送到行事件处理程序。根据源代码(https://github.com/nodejs/node/blob/master/lib/readline.js):
首先,检查"终端"已配置。如果不是,则使其等于输出流的isTTY属性:
if (terminal === undefined && !(output === null || output === undefined)) {
terminal = !!output.isTTY;
}
...
this.terminal = !!terminal;
其次,当调用rl.write()函数时,它将调用_ttyWrite()或_normalWrite(),具体取决于" terminal"是的:
Interface.prototype.write = function(d, key) {
...
this.terminal ? this._ttyWrite(d, key) : this._normalWrite(d);
};
最后,如果调用_ttyWrite(),数据将被发送到输出流。如果调用_normalWrite(),则忽略输出流:
//Interface.prototype._ttyWrite will invoke Interface.prototype._insertString, which will call Interface.prototype._writeToOutput
Interface.prototype._writeToOutput = function _writeToOutput(stringToWrite) {
...
if (this.output !== null && this.output !== undefined)
this.output.write(stringToWrite);
};
因此,当app.js直接在控制台中运行时,"你好"将打印,作为"终端"等于process.stdout.isTTY,这是真的。但是,在子进程中执行时," terminal"是false(如果未配置),因为process.stdout.isTTY现在未定义。