press any key to continue in nodejs
Asked Answered
E

15

50

I need a function that will pause the execution of the script until a key is pressed. I've tried:

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

but it's just listening for a keypress and nothing happens. The program does not continue executing.

How can I pause execution?

Evenhanded answered 30/10, 2013 at 15:43 Comment(1)
You can't pause the execution of script running in background. But I don't think that is the point, you need to pause the process.stdin/stdout. You can look into readline package.Botanomancy
D
30

Works for me:

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

process.stdin.setRawMode(true);
process.stdin.resume();
process.stdin.on('data', process.exit.bind(process, 0));
Drollery answered 30/10, 2013 at 19:52 Comment(4)
This is not a solution to the question, this kills the program on a keypress, the question was to pause and then resume on a keypress.Antherozoid
I got in process.stdin.setRawMode(true) TypeError: Object #<Socket> has no method 'setRawMode'Andrej
You have to put process.stdin.setRawMode=true instead of functionShift
Watch out if you're using nodemon!! process.stdin.setRawMode may be undefined.Biaxial
C
58

In node.js 7.6 and later you can do this:

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)

Or if you want CTRL-C to exit the program but any other key to continue normal execution, then you can replace the "keypress" function above with this function instead:

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()
  }))
}
Cutty answered 21/4, 2018 at 19:39 Comment(2)
If using the latest TypeScript version, select ES6 for tsconfig,json and change then(process.exit) to then(()=>process.exit(0)).Porche
For some reason the program was exiting at the process.stdin.once call. Adding the process.stdin.resume() after setRawMode(true), as suggested on @vkurchatkin answer, solved it. (Node 14.16.0)Tristichous
D
30

Works for me:

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

process.stdin.setRawMode(true);
process.stdin.resume();
process.stdin.on('data', process.exit.bind(process, 0));
Drollery answered 30/10, 2013 at 19:52 Comment(4)
This is not a solution to the question, this kills the program on a keypress, the question was to pause and then resume on a keypress.Antherozoid
I got in process.stdin.setRawMode(true) TypeError: Object #<Socket> has no method 'setRawMode'Andrej
You have to put process.stdin.setRawMode=true instead of functionShift
Watch out if you're using nodemon!! process.stdin.setRawMode may be undefined.Biaxial
T
18

The accepted solution waits asynchronously for a key event and then exits, it is not really a solution to "Press any key to continue".

I needed to pause while writing some nodejs shell scripts. I ended up using the spawnSync of the child_process with the shell command "read".

This will basically pause the script and when you press Enter it will continue. Much like the pause command in windows.

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

Hope this helps.

Tacy answered 25/2, 2017 at 21:32 Comment(2)
For Windows replace "read _ " with "pause". I check process.platform to set it based on the platform.Michalmichalak
simple and elegantPelmas
F
13

This snippet does the job if you don't want to exit the process:

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

It's async so won't work inside loop as-is-- if you're using Node 7 you could wrap it in a promise and use async/await.

Fumed answered 24/5, 2017 at 14:44 Comment(1)
Great no-nonsense stuff. You saved my afternoon.Ha
T
8

There is a package for this: press-any-key

And here is an example:

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')
  })

It runs without problems in W10.

Thermochemistry answered 13/2, 2019 at 10:2 Comment(0)
P
4
const fs = require('fs');
process.stdin.setRawMode(true);
fs.readSync(0, Buffer.alloc(1), 0, 1);

60% of the time, it works every time.

Portrait answered 4/9, 2019 at 21:35 Comment(0)
L
3
var fs = require("fs")
var fd = fs.openSync("/dev/stdin", "rs")
fs.readSync(fd, new Buffer(1), 0, 1)
fs.closeSync(fd)

This answer is taken from vadzim from node.js: readSync from stdin?

Lesleylesli answered 26/4, 2018 at 11:47 Comment(1)
This is UNIX-onlyMercaptide
S
2

Late to the party, but here's my hacky solution. Basically goDoWork doesn't get run until the promise resolves, which only happens when you press 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);
Shontashoo answered 14/1, 2021 at 16:24 Comment(0)
I
1

I did not see an encompassing answer yet. In particular, the answers using process.stdin.destroy() preclude the functions being called twice if you need multiple key presses. The ones that do not call process.stdin.off(...) keep processing key presses. The ones that do not call process.stdin.pause() keep the process alive even after the program completes.

I believe the following function is pretty thorough. Called without parameters, it displays a "Press any key to continue..." message and waits for the user to press any key. The message parameter overrides the default message. The keys parameter allows you to listen for particular keys, and the message will repeat if other keys are pressed. The accepted key pressed is not case-sensitive unless the keys parameter is mixed-case.

The return value is a Promise with the key the user pressed (case adjusted for non-case-sensitive keys). The promise is rejected if they press 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);
  });
}

Example 1: Shows Press any key to continue... message, waits for any key press.

await keyPress();

Example 2: Shows Process data? (Y|N): message, waiting for the user to press y, n, Y, or N. Repeats the message if other key is pressed. answer will be either 'y' or 'n', regardless of case pressed.

const answer = await keyPress("Process data? (Y|N): ", "yn");
Ironclad answered 23/6, 2021 at 4:4 Comment(0)
N
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

Noria answered 15/9, 2020 at 9:13 Comment(0)
R
0

I solved it, in my case, by turning the setRawMode to false, like this:

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));
}
Restoration answered 20/5, 2021 at 7:28 Comment(0)
F
0

If someone just looking for Press any key to EXIT!

console.log('Press any key to EXIT!');
process.openStdin().on('data',()=>{process.exit('0')});
Fanni answered 5/11, 2023 at 7:5 Comment(0)
E
0

Install readline-sync in your project.

npm install readline-sync

Then you can use in your js

const readlineSync = require('readline-sync');
readlineSync.keyInPause();

It is simple.

Expurgatory answered 29/2 at 15:1 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Sideband
K
-1

Press any key to continue

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

Thanks @vkurchatkin

Karimakarin answered 14/1, 2021 at 2:16 Comment(0)
O
-3

I actually made an npm package called paktc that will help you with this. If you install the package:

> npm install paktc

Then you would use it like this:

// your console application code here...

require('paktc') // Press any key to continue...
Ofeliaofella answered 6/6, 2014 at 16:50 Comment(4)
Paktc does not work at all, it depends on a global called v8debug which don't care to research, but it's not in a normal node environment.Exterminate
It's only there when a debugger is actually attached. Just tried it again in node 5, still works.Ofeliaofella
Meaning if you run node --debug it will only open the debugger port but will not necessarily debug unless you attach something to it. If you do, instead node --debug-brk then it will actually break when the process launches and attach a console debugger to it. At that point the global v8debug variable is found.Ofeliaofella
Lol, no. You'd have to clear the require cache and then require it again obviously. But seriously this was my first npm library and it's terrible, lol. But I learned a lot.Ofeliaofella

© 2022 - 2024 — McMap. All rights reserved.