39

我需要一个函数来暂停脚本的执行,直到按下一个键。我试过了:

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

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

如何暂停执行?

4

13 回答 13

41

在 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 退出程序但任何​​其他键继续正常执行,那么您可以将上面的“keypress”函数替换为此函数:

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()
  }))
}
于 2018-04-21T19:39:10.337 回答
29

为我工作:

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

process.stdin.setRawMode(true);
process.stdin.resume();
process.stdin.on('data', process.exit.bind(process, 0));
于 2013-10-30T19:52:42.810 回答
12

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

在编写一些 nodejs shell 脚本时,我需要暂停一下。我最终将 child_process 的 spawnSync 与 shell 命令“read”一起使用。

这基本上会暂停脚本,当您按 Enter 时它将继续。很像 Windows 中的暂停命令。

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

希望这可以帮助。

于 2017-02-25T21:32:19.110 回答
10

如果您不想退出该过程,则此代码段可以完成工作:

console.log('Press any key to continue.');
process.stdin.once('data', function () {
  continueDoingStuff();
});

它是异步的,所以不能在循环中按原样工作——如果你使用的是 Node 7,你可以将它包装在一个 Promise 中并使用async/await.

于 2017-05-24T14:44:32.597 回答
4

有一个包: 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 中运行没有问题。

于 2019-02-13T10:02:19.417 回答
3
const fs = require('fs');
process.stdin.setRawMode(true);
fs.readSync(0, Buffer.alloc(1), 0, 1);

60%的时间,它每次都有效。

于 2019-09-04T21:35:54.090 回答
2

聚会迟到了,但这是我的老生常谈的解决方案。基本上 goDoWork 在承诺解决之前不会运行,这仅在您按 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);
于 2021-01-14T16:24:22.050 回答
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 的 vadzim: readSync from stdin?

于 2018-04-26T11:47:19.440 回答
1

我还没有看到一个全面的答案。特别是,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");
于 2021-06-23T04:04:47.193 回答
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));
}
于 2021-05-20T07:28:13.460 回答
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...');

参考

于 2020-09-15T09:13:14.273 回答
-1

按任意键继续

function pressAnyKey(msg = 'Press any key to continue') {
    return new Promise((resolve) => {
        console.log(msg || 'Press any key to continue');
        process.stdin.setRawMode(true);
        process.stdin.resume();
        process.stdin.on('data', () => {
            process.stdin.destroy();
            resolve();
        });
    });
}

(async () => {
    await pressAnyKey();
    console.log('hello');
})();

// timeout version

function pressAnyKey(msg = 'Press any key to continue', timeout = 3000) {
    return new Promise((resolve) => {
        let handler = null;
        const end = () => {
            process.stdin.destroy();
            if (handler) clearTimeout(handler);
            resolve();
        }
        console.log(msg || 'Press any key to continue');
        process.stdin.setRawMode(true);
        process.stdin.resume();
        process.stdin.on('data', end);
        handler = setTimeout(end, Math.max(1, timeout));
    });
}

谢谢@vkurchatkin

于 2021-01-14T02:16:17.027 回答
-3

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

> npm install paktc

然后你会像这样使用它:

// your console application code here...

require('paktc') // Press any key to continue...
于 2014-06-06T16:50:21.540 回答