-
-
Notifications
You must be signed in to change notification settings - Fork 306
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Keypress events may not be triggered on Windows if validate callback contains async actions #402
Comments
Based on Prompts library code, I have made a minimal example of how this issue can be reproduced using only Node. const { stdin, stdout } = require('process');
const readline = require('readline');
const fetch = require('node-fetch');
// makes input stream emit 'keypress' events
function createReadline(is, keypress) {
const rl = readline.createInterface({
input: is,
escapeCodeTimeout: 50
});
readline.emitKeypressEvents(is, rl);
if (is.isTTY) {
is.setRawMode(true);
}
is.on('keypress', keypress);
// return a callback that stops emitting 'keypress' events and frees resources
return () => {
is.removeListener('keypress', keypress);
if (is.isTTY) {
is.setRawMode(false);
}
rl.close();
};
}
// determine what is needed to do for a key object sent by 'keypress' event
function getActionName(key) {
function needFinish(key) {
return (key.ctrl && ['c', 'd'].includes(key.name)) ||
key.name == 'escape' ||
['enter', 'return'].includes(key.name);
}
function doNothing(key) {
return ['backspace', 'delete', 'abort', 'escape', 'tab', 'pagedown', 'pageup',
'home', 'end', 'up', 'down', 'right', 'left'].includes(key.name) || key.ctrl;
}
if (doNothing(key)) {
return 'noop';
}
if (needFinish(key)) {
return 'finish';
}
return 'add-letter';
}
// listen to keypresses until user presses Enter, and then return concatenated letters
function input(is, os, onEndInput = () => undefined) {
return new Promise((resolve) => {
os.write('Enter string letter by letter, then press Enter\n');
let result = '';
const closeReadline = createReadline(is, keypress);
function keypress(_, key) {
os.write(`Encountered ${key.name}\n`)
const actionName = getActionName(key);
if (actionName == 'finish') {
endInput();
} else if (actionName == 'add-letter') {
result += key.name;
}
};
async function endInput() {
await onEndInput();
closeReadline();
resolve(result);
};
});
}
async function asyncAction() {
await fetch('https://jsonplaceholder.typicode.com/posts');
}
async function main() {
await input(stdin, stdout, asyncAction);
await input(stdin, stdout);
await input(stdin, stdout);
}
main(); |
Based on the new answer in the issue I opened in node repo, here is a workaround that resolves the issue: In my example closeReadline();
resolve(result); Should be wrapped into |
Describe the bug
When showing promtps multiple times, if one of the prompt inputs is validated using async actions, keypresses on other prompts may be missed. Happens only on Windows.
To Reproduce
Steps to reproduce the behavior:
Actual behavior
On node 16.20.2: on "Prompt 3" no keypress events are triggered untill Enter key is pressed - then the input can be entered as usual; if you remove
fetch
call fromvalidate
callback then everything will work perfectly.On node 20.6.1: on "Prompt 3", on the first key press, no keypress event is triggered. The second and all next keypresses will be handled correctly.
Also, I have a project which I cannot post here, there I have the behavior described for node 16.20.2 even when it is run on 20.6.1.
Expected behavior
All key presses should be handled correctly.
System
Additional context
It may be Node issue. I encountered similar issues in this repo, still there wasn't anything about validate callback there.
The text was updated successfully, but these errors were encountered: