繁体   English   中英

按任意键在 nodejs 中继续

[英]press any key to continue in nodejs

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

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

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

如何暂停执行?

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

对我有用:

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

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

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

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

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

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

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

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

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

希望这会有所帮助。

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

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?

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

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

聚会迟到了,但这是我的hacky解决方案。 基本上 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);
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...');

参考

在我的情况下,我通过将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));
}

我还没有看到一个全面的答案。 特别是,如果您需要多次按键,使用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): Process data? (Y|N):消息,等待用户按ynYN 如果按下其他键,则重复该消息。 answer将是'y''n' ,无论按下大小写。

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

按任意键继续

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

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

> npm install paktc

然后你会像这样使用它:

// your console application code here...

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM