Node.js中readline按键监听器导致程序无法自动退出的问题
Node.js TUI应用监听单次按键后进程无法自动退出
我正尝试为Node.js TUI应用编写一个可await的异步函数,要求无需按回车即可监听单次键盘按键,并返回按键信息,且不使用任何NPM包。
我的函数代码如下:
export async function inkey_promise() { console.log('Press any key...'); return new Promise((resolve) => { readline.emitKeypressEvents(process.stdin); process.stdin.setRawMode(true); const listener = (str, readline_key) => { process.stdin.setRawMode(false); process.stdin.resume(); console.log(`RETURNING: `, readline_key); return resolve(readline_key); }; process.stdin.once('keypress', listener); }); }
调用方式:
const key_info = await inkey_promise();
问题:按下按键后,Promise正常resolve,后续代码也能正常执行,但当程序无任务可执行时,会一直运行无法自动退出,除非手动终止进程。我不想显式调用process.exit(),因为按键后程序通常还有任务执行,但无任务时应正常退出。似乎需要将process/stdin/键盘完全恢复到默认状态?
解决方案
问题根源是你没有将stdin完全恢复到启动时的默认状态,导致进程持续监听stdin输入,无法自动退出。以下是修正后的函数:
import readline from 'readline'; // 确保导入readline模块 export async function inkey_promise() { console.log('Press any key...'); return new Promise((resolve) => { readline.emitKeypressEvents(process.stdin); process.stdin.setRawMode(true); process.stdin.resume(); // 临时恢复stdin以接收按键 const listener = (str, readline_key) => { // 恢复默认终端模式 process.stdin.setRawMode(false); // 暂停stdin,回到Node.js启动时的默认状态 process.stdin.pause(); // 显式移除监听(配合once双重保险) process.stdin.off('keypress', listener); // 清理readline关联的终端状态 readline.clearLine(process.stdin, 0); console.log(`RETURNING: `, readline_key); resolve(readline_key); }; process.stdin.once('keypress', listener); }); }
关键修正点:
- 调用
process.stdin.pause():Node.js启动时stdin默认处于暂停状态,之前只调用了resume()但未恢复,导致进程持续监听stdin无法退出。 - 添加
process.stdin.off('keypress', listener):虽然用了once,显式移除监听可避免潜在的残留绑定问题。 - 使用
readline.clearLine():清理readline遗留的终端状态,确保环境完全重置。
修改后,当程序无后续任务时,进程会因stdin不再被监听而正常退出,无需手动调用process.exit()。
内容的提问来源于stack exchange,提问作者LaVache
相关产品推荐
相关产品推荐

