使用Readline异步读取标准输入遇异步执行问题求助
问题描述
我正在查看O'Reilly书籍《JavaScript权威指南》中的一个示例并尝试修改。原示例使用输入重定向(node charfreq.js < input.txt)时运行正常,但我希望改成让用户在Windows命令行手动输入内容,按下Ctrl+Z(Windows下结束输入的快捷键,按后回车)后脚本再继续执行。尝试用readline替代process.stdin时,搞不定异步逻辑。
原始代码:
async function histogramFromStdin() { process.stdin.setEncoding("utf-8"); // 读取Unicode字符串而非字节 let histogram = new Histogram(); for await (let chunk of process.stdin) { histogram.add(chunk); } return histogram; } // 程序主逻辑:从标准输入生成直方图并打印 histogramFromStdin().then(histogram => { console.log(histogram.toString()); });
我的尝试:
问题在于console.log(histogram.toString());会立即执行,此时histogram还是未定义状态,不知道该在何处添加await。
async function histogramFromStdin() { var readline = require('readline'); process.stdin.setEncoding('utf-8'); let histogram = new Histogram(); var rl = readline.createInterface({ input: process.stdin, output: process.stdout }); rl.setPrompt('> '); rl.prompt(); rl.on('line', function (chunk) { histogram.add(chunk); rl.prompt(); }); rl.on('close', function () { console.log('Input has closed'); return histogram; }); } // 程序主逻辑:从标准输入生成直方图并打印 histogramFromStdin().then(histogram => { console.log(histogram.toString()); });
解决方案
核心是把readline的回调逻辑包装成Promise,让异步函数能等待输入完成后再返回结果:
async function histogramFromStdin() { const readline = require('readline'); process.stdin.setEncoding('utf-8'); let histogram = new Histogram(); // 用Promise包裹readline的事件逻辑 return new Promise((resolve) => { const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); rl.setPrompt('> '); rl.prompt(); // 处理每一行输入 rl.on('line', (chunk) => { histogram.add(chunk); rl.prompt(); }); // 输入结束时返回直方图 rl.on('close', () => { console.log('输入已结束'); resolve(histogram); }); }); } // 主程序逻辑 histogramFromStdin().then(histogram => { console.log(histogram.toString()); });
说明
- 原代码中
histogramFromStdin是async函数,但内部readline基于回调,函数会直接返回undefined,导致then里拿到的是未定义的结果。 - 用Promise包裹后,当
close事件触发时,通过resolve(histogram)把最终结果传递出去,async函数会等待这个Promise完成,返回正确的Histogram实例。 - Windows命令行中,按下Ctrl+Z再回车就能触发
close事件,结束输入。
内容的提问来源于stack exchange,提问作者Flack
相关产品推荐
相关产品推荐

