使用@inquirer/prompts连续调用两个Prompt时程序异常终止的问题
嘿,这个问题我之前用@inquirer的时候也踩过坑!你遇到的情况应该是第一个prompt处理Ctrl+C后,终端的交互状态没被正确重置,导致第二个prompt根本没法正常拉起交互环境,刚打印完消息就直接退出了。
咱们来拆解下原因:@inquirer底层依赖readline模块和终端交互,当你按下Ctrl+C触发SIGINT信号时,第一个prompt的try/catch虽然捕获了中断,但@inquirer内部可能已经关闭了readline实例、修改了终端的raw模式,甚至调整了默认的信号监听器。这时候第二个prompt启动时,发现终端环境不对,就直接默认退出了,所以你看到退出码是0(看似正常退出,但完全不是你想要的结果)。
给你几个实用的解决办法:
手动恢复终端状态与信号监听
在第一个prompt的catch块里,手动把终端恢复到原始模式,并且重置SIGINT的处理逻辑,这样第二个prompt就能正常初始化了。比如可以这么写:import { input, confirm } from '@inquirer/prompts'; async function collectUserInputs() { try { while (true) { const inputValue = await input({ message: '输入内容(按Ctrl+C结束):' }); // 这里处理你的输入逻辑 console.log(`已接收输入: ${inputValue}`); } } catch (err) { console.log('\n输入收集完成'); // 恢复终端的原始模式,不然后续prompt没法正常工作 process.stdin.setRawMode(false); // 移除可能存在的自定义SIGINT监听器,交给第二个prompt自己处理 process.removeAllListeners('SIGINT'); } } async function main() { await collectUserInputs(); // 现在第二个确认prompt就能正常工作了 const confirmResult = await confirm({ message: '是否继续执行后续操作?' }); console.log(`你的选择是: ${confirmResult}`); } main();别自己瞎绑定SIGINT监听器
很多人会想着自己加process.on('SIGINT', ...)来处理中断,但其实@inquirer本身已经内置了SIGINT的处理逻辑,手动绑定反而会和它的内部逻辑冲突,导致终端状态混乱。就用try/catch捕获第一个prompt的中断就行,别画蛇添足。检查资源是否泄漏
如果你的第一个循环里有其他和终端交互的资源(比如自己创建的readline实例),一定要在退出循环时关闭它们,不然这些资源会占用终端控制权,第二个prompt根本拿不到权限,自然就直接退出了。
备注:内容来源于stack exchange,提问作者Nipun

