Node.js readline模块异常:获取用户输入后程序停滞
Node.js readline输入后程序停滞问题排查与修复
问题概述
使用JavaScript解决DSA问题时,通过Node.js的readline/promises模块获取用户输入,程序在完成输入后陷入停滞,无任何报错信息。
提供的代码
业务代码
/* Given an array and Q queries, where a query looks like the following, (l,r)--> l,r are the indices of the array. For each query, you need to find the sum between the given indices */ import { getUserInput } from "../index.js"; async function preCompute() { let arraySize = 0; // get the number for user inputs arraySize = await getUserInput("Enter the array size : "); console.log("ARRAY SIZE", arraySize); const userInputs = []; for (let i = 0; i < Number(arraySize.trim()); i++) { const currentUserInput = await getUserInput("Enter the number"); userInputs.push(Number(currentUserInput.trim())); } const prefixSumArray = []; for (let i = 0; i < arraySize; i++) { if (i === 0) { prefixSumArray[i] = userInputs[i]; } else { prefixSumArray[i] = prefixSumArray[i - 1] + userInputs[i]; } } let Q = 0; Q = await getUserInput("Enter the number of queries i.e Q"); for (let i = 0; i < Q; i++) { const queryInput = await getUserInput( "Enter space separated value for l and r" ); const [l, r] = queryInput.split(" "); console.log( `Sum between l and r: ${\n l !== 0 ? prefixSumArray[r] - prefixSumArray[l - 1] : prefixSumArray[r]\n }` ); } } preCompute();
index.js代码
import readline from "node:readline/promises"; import { stdin as input, stdout as output } from "node:process"; const rl = readline.createInterface({ input, output, }); export const getUserInput = (prompt) => { return new Promise((resolve) => { rl.question(prompt, (answer) => { console.log("Running callback to resolve"); resolve(answer); }); }); };
问题原因分析
- readline接口未关闭:创建的
rl实例在所有输入操作完成后没有调用rl.close(),Node.js会保持标准输入(stdin)的监听状态,导致事件循环无法退出,程序看起来陷入停滞。 - 输入未显式转换为数字:
arraySize、Q等变量直接使用字符串类型参与循环条件判断,虽然JavaScript会隐式转换,但容易引发意外问题(比如输入包含非数字字符时循环逻辑出错)。 - 模板字符串语法错误:console.log中的模板字符串存在语法错误,表达式部分的换行写法不符合规范,可能导致程序静默失败或输出异常。
解决方案
1. 完成输入后关闭readline接口
在所有输入和查询处理完成后,调用rl.close()终止readline接口的监听,让Node.js事件循环正常退出。
2. 显式转换输入为数字
将获取的用户输入统一转换为数字类型,避免隐式转换带来的潜在问题。
3. 修复模板字符串语法错误
调整模板字符串中表达式的写法,确保语法合规。
修改后的代码示例
修改后的index.js
import readline from "node:readline/promises"; import { stdin as input, stdout as output } from "node:process"; export const rl = readline.createInterface({ input, output, }); export const getUserInput = (prompt) => { return new Promise((resolve) => { rl.question(prompt, (answer) => { console.log("Running callback to resolve"); resolve(answer.trim()); }); }); };
修改后的业务代码
import { getUserInput, rl } from "../index.js"; async function preCompute() { try { // 获取数组大小并转为数字 const arraySizeStr = await getUserInput("Enter the array size : "); const arraySize = Number(arraySizeStr); console.log("ARRAY SIZE", arraySize); // 获取数组元素 const userInputs = []; for (let i = 0; i < arraySize; i++) { const numStr = await getUserInput(`Enter number ${i + 1}: `); userInputs.push(Number(numStr)); } // 计算前缀和 const prefixSumArray = []; for (let i = 0; i < arraySize; i++) { prefixSumArray[i] = i === 0 ? userInputs[i] : prefixSumArray[i - 1] + userInputs[i]; } // 获取查询次数并转为数字 const QStr = await getUserInput("Enter the number of queries i.e Q: "); const Q = Number(QStr); // 处理查询 for (let i = 0; i < Q; i++) { const queryInput = await getUserInput("Enter space separated value for l and r: "); const [lStr, rStr] = queryInput.split(" "); const l = Number(lStr); const r = Number(rStr); // 校验索引合法性 if (l < 0 || r >= arraySize || l > r) { console.log("Invalid indices: l and r must be within array bounds and l <= r"); continue; } const sum = l !== 0 ? prefixSumArray[r] - prefixSumArray[l - 1] : prefixSumArray[r]; console.log(`Sum between l=${l} and r=${r}: ${sum}`); } } catch (err) { console.error("Error occurred:", err); } finally { // 关闭readline接口,让程序正常退出 rl.close(); } } preCompute();
额外说明
- 添加
try/catch块处理可能的异常(比如输入非数字时的转换错误),提升程序健壮性。 - 对查询的索引进行合法性校验,避免数组越界错误。
- 在
getUserInput中自动trim输入,减少后续重复处理。
内容的提问来源于stack exchange,提问作者Abhishek Sharma
相关产品推荐
相关产品推荐

