按任意键继续在nodejs中

时间:2013-10-30 15:43:01

标签: javascript node.js keypress

我需要一个暂停执行脚本的功能,直到按下某个键。 我试过了:

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();
});

但它只是在听按键而没有任何反应。该程序不会继续执行。

如何暂停执行?

12 个答案:

答案 0 :(得分:18)

适合我:

console.log('Press any key to exit');

process.stdin.setRawMode(true);
process.stdin.resume();
process.stdin.on('data', process.exit.bind(process, 0));

答案 1 :(得分:9)

在node.js 7.6及更高版本中,您可以这样做:

const keypress = async () => {
  process.stdin.setRawMode(true)
  return new Promise(resolve => process.stdin.once('data', () => {
    process.stdin.setRawMode(false)
    resolve()
  }))
}

;(async () => {

  console.log('program started, press any key to continue')
  await keypress()
  console.log('program still running, press any key to continue')
  await keypress()
  console.log('bye')

})().then(process.exit)

或者如果你想让CTRL-C退出程序但是任何其他键继续正常执行,那么你可以替换"按键"以上功能改为:

const keypress = async () => {
  process.stdin.setRawMode(true)
  return new Promise(resolve => process.stdin.once('data', data => {
    const byteArray = [...data]
    if (byteArray.length > 0 && byteArray[0] === 3) {
      console.log('^C')
      process.exit(1)
    }
    process.stdin.setRawMode(false)
    resolve()
  }))
}

答案 2 :(得分:4)

如果您不想退出该过程,此片段可以完成此任务:

writeValueAsString()

它是异步的,所以不会在循环内部工作 - 如果你使用的是Node 7,你可以将它包装在一个promise中并使用console.log('Press any key to continue.'); process.stdin.once('data', function () { continueDoingStuff(); });

答案 3 :(得分:3)

接受的解决方案异步等待一个关键事件然后退出,它实际上并不是“按任意键继续”的解决方案。

我需要在编写一些nodejs shell脚本时暂停。我最后使用shell命令“read”使用了child_process的spawnSync。

这将基本暂停脚本,当您按Enter键时,它将继续。很像windows中的pause命令。

require('child_process').spawnSync("read _ ", {shell: true, stdio: [0, 1, 2]});

希望这有帮助。

答案 4 :(得分:2)

var fs = require("fs")
var fd = fs.openSync("/dev/stdin", "rs")
fs.readSync(fd, new Buffer(1), 0, 1)
fs.closeSync(fd)

此答案取自node.js: readSync from stdin?

的vadzim

答案 5 :(得分:2)

聚会迟到了,但这是我的笨拙解决方案。基本上 goDoWork 在 promise 解决之前不会运行,这只会在您按下 Enter 键时发生。

let resolv = null;
const promise = new Promise((resolve, reject) => {
    resolv = resolve;
})

var stdin = process.openStdin();
console.log('Press enter to continue');
stdin.on('data', () => {
    resolv();
    console.log("Key pressed");
});

promise.then(goDoWork);

答案 6 :(得分:0)

有一个用于此的程序包: press-any-key

这是一个示例:

const pressAnyKey = require('press-any-key');
pressAnyKey("Press any key to resolve, or CTRL+C to reject", {
  ctrlC: "reject"
})
  .then(() => {
    console.log('You pressed any key')
  })
  .catch(() => {
    console.log('You pressed CTRL+C')
  })

它在W10中运行没有问题。

答案 7 :(得分:0)

const fs = require('fs');
process.stdin.setRawMode(true);
fs.readSync(0, Buffer.alloc(1), 0, 1);

60%的时间,它每次都能工作。

答案 8 :(得分:0)

const readline = require('readline');
readline.emitKeypressEvents(process.stdin);
process.stdin.setRawMode(true);
process.stdin.on('keypress', (str, key) => {
  if (key.ctrl && key.name === 'c') {
    process.exit();
  } else {
    console.log(`You pressed the "${str}" key`);
    console.log();
    console.log(key);
    console.log();
  }
});
console.log('Press any key...');

reference

答案 9 :(得分:0)

就我而言,我通过将 setRawMode 变为 false 来解决它,如下所示:

setRawMode(value) {
    if (process.stdin.isTTY) {
        process.stdin.setRawMode(value);
    }
}

confirm(settings) {
    logUtils.log(logService.createConfirmSettingsTemplate(settings));
    readline.emitKeypressEvents(process.stdin);
    this.setRawMode(true);
    return new Promise((resolve, reject) => {
        try {
            process.stdin.on('keypress', (chunk, key) => {
                if (chunk) { }
                resolve(key && key.name === 'y');
                this.setRawMode(false);
            });
        }
        catch (error) {
            this.setRawMode(false);
            reject(false);
        }
    }).catch(this.setRawMode(false));
}

答案 10 :(得分:0)

我还没有看到全面的答案。特别是,如果您需要多次按键,使用 process.stdin.destroy() 的答案会阻止函数被调用两次。不调用 process.stdin.off(...) 的那些继续处理按键。那些不调用 process.stdin.pause() 的进程即使在程序完成后也会保持进程处于活动状态。

我相信下面的功能是相当彻底的。不带参数调用,它显示 "Press any key to continue..." 消息并等待用户按任意键。 message 参数覆盖默认消息。 keys 参数允许您侦听特定键,如果按下其他键,消息将重复。接受的按键不区分大小写,除非 keys 参数是大小写混合的。

返回值是带有用户按下的键的 Promise(大小写调整为不区分大小写的 keys)。如果他们按下 CTRL-c,承诺将被拒绝。

function keyPress(message, keys) {
  const _message = message || "Press any key to continue...";
  const _keys = keys || "";
  return new Promise(function (resolve, reject) {
    const caseSensitive = _keys.toLowerCase() !== _keys && _keys.toUpperCase() !== _keys;
    process.stdout.write(_message);
    function keyListener(buffer) {
      let key = buffer.toString();
      if (key.charCodeAt(0) === 3) {
        process.stdin.setRawMode(false);
        process.stdin.off('data', keyListener);
        process.stdin.pause();
        // process.exit(0); // Exit process if you prefer.
        reject(key.charCodeAt(0));
      }
      const index = caseSensitive ? _keys.indexOf(key) : _keys.toLowerCase().indexOf(key.toLowerCase());
      if (_keys && index < 0) {
        process.stdout.write(key);
        process.stdout.write("\n");
        process.stdout.write(_message);
        return;
      }
      process.stdin.setRawMode(false);
      process.stdin.off('data', keyListener);
      process.stdin.pause();
      if (index >= 0) {
        key = _keys.charAt(index);
        process.stdout.write(key);
      }
      process.stdout.write("\n");
      resolve(key);
    }
    process.stdin.resume();
    process.stdin.setRawMode(true);
    process.stdin.on('data', keyListener);
  });
}

示例 1:显示 Press any key to continue... 消息,等待任何按键按下。

await keyPress();

示例 2:显示 Process data? (Y|N): 消息,等待用户按 ynYN。如果按下其他键,则重复该消息。 answer 将是 'y''n',无论按下大小写。

const answer = await keyPress("Process data? (Y|N): ", "yn");

答案 11 :(得分:-1)

我实际上制作了一个名为paktc的npm包,可以帮助你解决这个问题。如果您安装包:

> npm install paktc

然后你会像这样使用它:

// your console application code here...

require('paktc') // Press any key to continue...