Nodejs 如何从 stdin 中读取击键

是否可以侦听正在运行的 nodejs 脚本中传入的击键? 如果我使用 process.openStdin()并监听它的 'data'事件,那么输入将被缓冲到下一个换行符,如下所示:

// stdin_test.js
var stdin = process.openStdin();
stdin.on('data', function(chunk) { console.log("Got chunk: " + chunk); });

运行这个,我得到:

$ node stdin_test.js
<-- type '1'
<-- type '2'
<-- hit enter
Got chunk: 12

我想看到的是:

$ node stdin_test.js
<-- type '1' (without hitting enter yet)
Got chunk: 1

我正在寻找一个 nodejs 等价于,例如,红宝石 getc

这可能吗?

119428 次浏览

你可以这样做,如果你切换到原始模式:

var stdin = process.openStdin();
require('tty').setRawMode(true);


stdin.on('keypress', function (chunk, key) {
process.stdout.write('Get Chunk: ' + chunk + '\n');
if (key && key.ctrl && key.name == 'c') process.exit();
});

使用 nodejs 0.6.4测试(在0.8.14版本中测试失败) :

rint = require('readline').createInterface( process.stdin, {} );
rint.input.on('keypress',function( char, key) {
//console.log(key);
if( key == undefined ) {
process.stdout.write('{'+char+'}')
} else {
if( key.name == 'escape' ) {
process.exit();
}
process.stdout.write('['+key.name+']');
}


});
require('tty').setRawMode(true);
setTimeout(process.exit, 10000);

如果你运行它:

  <--type '1'
{1}
<--type 'a'
{1}[a]

重要代码 # 1:

require('tty').setRawMode( true );

重要代码 # 2:

.createInterface( process.stdin, {} );

此版本使用 按键模块,并支持 node.js 版本0.10、0.8和0.6以及 iojs 2.3。一定要运行 npm install --save keypress

var keypress = require('keypress')
, tty = require('tty');


// make `process.stdin` begin emitting "keypress" events
keypress(process.stdin);


// listen for the "keypress" event
process.stdin.on('keypress', function (ch, key) {
console.log('got "keypress"', key);
if (key && key.ctrl && key.name == 'c') {
process.stdin.pause();
}
});


if (typeof process.stdin.setRawMode == 'function') {
process.stdin.setRawMode(true);
} else {
tty.setRawMode(true);
}
process.stdin.resume();

对于那些因为从 tty中剥离了这个功能而找到这个答案的人,以下是如何从 stdin 获取原始字符流的方法:

var stdin = process.stdin;


// without this, we would only get streams once enter is pressed
stdin.setRawMode( true );


// resume stdin in the parent process (node app won't quit all by itself
// unless an error or process.exit() happens)
stdin.resume();


// i don't want binary, do you?
stdin.setEncoding( 'utf8' );


// on any data into stdin
stdin.on( 'data', function( key ){
// ctrl-c ( end of text )
if ( key === '\u0003' ) {
process.exit();
}
// write the key to stdout all normal like
process.stdout.write( key );
});

非常简单——基本上就像 Process.stdin 的文档一样,但是使用 setRawMode( true )获得原始流,这在文档中很难确定。

if(process.stdout.isTTY){
process.stdin.on("readable",function(){
var chunk = process.stdin.read();
if(chunk != null) {
doSomethingWithInput(chunk);
}
});
process.stdin.setRawMode(true);
} else {
console.log("You are not using a tty device...");
}

在 node > = v6.1.0中:

const readline = require('readline');


readline.emitKeypressEvents(process.stdin);
process.stdin.setRawMode(true);


process.stdin.on('keypress', (str, key) => {
console.log(str)
console.log(key)
})

参见 https://github.com/nodejs/node/issues/6626

根据 Dan Heberden 的回答,这里有一个异步函数-

async function getKeypress() {
return new Promise(resolve => {
var stdin = process.stdin
stdin.setRawMode(true) // so get each keypress
stdin.resume() // resume stdin in the parent process
stdin.once('data', onData) // like on but removes listener also
function onData(buffer) {
stdin.setRawMode(false)
resolve(buffer.toString())
}
})
}

像这样使用

console.log("Press a key...")
const key = await getKeypress()
console.log(key)

这将输出每个按键。

process.stdin.setRawMode(true).setEncoding('utf8').resume().on('data',k=>console.log(k))