【问题标题】:Using readline module in node.js, how do I ask a certain number of questions, but not ask the next question before previous answer is received在node.js中使用readline模块,我如何问一定数量的问题,但在收到上一个答案之前不问下一个问题
【发布时间】:2025-12-20 13:35:16
【问题描述】:

例如,如果这是我的代码

var rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
    terminal: false,
});

for(var i = 0;i<7;i++){
    rl.question('What is your name? ', function(name){
        console.log("Your name is " + name);
    });
}

然后当我在 CLI 中运行它时,我得到的提示是

What is your name?What is your name?What is your name?What is your name?What is your name?What is your name?What is your name?

如何让它询问“你叫什么名字?”,然后得到答案,然后显示输出,然后再重复 6 次。 谢谢!

【问题讨论】:

    标签: node.js readline


    【解决方案1】:

    默认情况下,question 方法是基于回调的。这意味着要问第二个问题,您需要在第一个 question 调用的回调中调用第二个 rl.question

    这种方法非常脆弱,在您的情况下根本无法扩展,因为您最终会得到一个嵌套回调的深金字塔。

    因此,一种策略可能是将这个基于回调的 API 转变为基于 Promise 的 API。幸运的是,Node.js 在util 模块中提供了一个方便的promisify 帮助器,可以执行此转换。

    这在官方文档中有详细说明:https://nodejs.org/dist/latest-v15.x/docs/api/readline.html

    有了这个新的promisified question 函数返回一个promise,您现在可以使用async/await 语法来获得您所期望的:

    var readline = require('readline');
    var util = require('util');
    
    var rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout,
        terminal: false
    });
    
    var question = util.promisify(rl.question).bind(rl);
    
    async function ask() {
        for(var i = 0;i<7;i++){
            try {
                var name = await question('What is you name? ');
                console.log("Your name is " + name);
            } catch (err) {
                console.error('Question rejected', err);
            }
        }
        rl.close();
    }
    
    ask()
    

    【讨论】:

    • 您好,谢谢您的回复。我试过了,虽然排序现在正常工作,在上一个响应之后询问下一个问题,现在发生的事情是它会将所有响应作为错误捕获(输入和输出如下所示)What is you name? temp Question rejected temp你如何建议这个问题应该解决吗?
    【解决方案2】:

    util.promisify 让你接近,但它需要一个有两个参数的函数:一个错误和一个值。 rl.question 不满足这个接口:它总是用一个参数调用函数,即输入。 util.promisify 将此输入视为非空,因此假定发生了错误。

    幸运的是,util.promisify 是一个超级简单的函数,我们可以自己重写它以在这个用例中工作。

    const question = (...args) => new Promise((res, rej) => rl.question(...args, res));
    

    现在question 是一个产生承诺的函数。我们可以异步它。其余代码的工作方式与 Delapouite 的答案相同

    async function ask() {
        for(var i = 0;i<7;i++){
            try {
                var name = await question('What is you name? ');
                console.log("Your name is " + name);
            } catch (err) {
                console.error('Question rejected', err);
            }
        }
        rl.close();
    }
    
    ask()
    

    【讨论】: