【问题标题】:Using readline in Node.js在 Node.js 中使用 readline
【发布时间】:2018-10-11 18:39:57
【问题描述】:

我正在尝试在 else if 语句中使用 readline

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

rl.question("Would you like to see which cars are available? Please type yes/no: ", function(answer) {

    if (answer === 'yes') {
    // if yes do something
    } else if(answer === 'no') {
        rl.question("Would you like to search by latitude or longitude instead? If yes, please type latitude and longitude: ");
    } else {
        console.log("No worries, have a nice day");
    }

    rl.close();
});

如果用户输入“否”,向用户提出不同问题的正确方法是什么?

目前,如果用户输入“否”,则不会询问第二个问题。

【问题讨论】:

  • 我只是想知道你是否知道你的代码出了什么问题,因为你接受了一个实际上并没有回答你的问题的答案?

标签: javascript node.js if-statement input readline


【解决方案1】:

如果我要这样做,我会先创建一个基于 promise 的 readLine question 函数版本:

const question = (str) => new Promise(resolve => rl.question(str, resolve));

我会将其构建为一组步骤:

const steps = {
  start: async () => {
    return steps.seeCars();
  },
  seeCars: async () => {
    const seeCars = await question("Would you like to see which cars are available? Please type yes/no: ");
    if (seeCars === 'yes') { return steps.showCars(); }
    if (seeCars === 'no') { return steps.locationSearch(); }
    console.log('No worries, have a nice day');
    return steps.end();
  },
  showCars: async () => {
    console.log('showing cars');
    return steps.end();
  },
  locationSearch: async () => {
    const longlat = await question("Would you like to search by latitude or longitude instead? If yes, please type latitude and longitude: ");
    return steps.end();
  },
  end: async () => {
    rl.close();
  },
};

如果您不熟悉异步函数,请注意您必须在问题前输入 await 以指示节点在问题得到答案之前不要继续。

另请注意,每当我们更改步骤时,您都需要return,以便该步骤的其余部分不会运行。

这里有完整的程序供你复制和玩:

const readline = require('readline');

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

// Create a promise based version of rl.question so we can use it in async functions
const question = (str) => new Promise(resolve => rl.question(str, resolve));

// A list of all the steps involved in our program
const steps = {
  start: async () => {
    return steps.seeCars();
  },
  seeCars: async () => {
    const seeCars = await question("Would you like to see which cars are available? Please type yes/no: ");
    if (seeCars === 'yes') { return steps.showCars(); }
    if (seeCars === 'no') { return steps.locationSearch(); }
    console.log('No worries, have a nice day');
    return steps.end();
  },
  showCars: async () => {
    console.log('showing cars');
    return steps.end();
  },
  locationSearch: async () => {
    const longlat = await question("Would you like to search by latitude or longitude instead? If yes, please type latitude and longitude: ");
    return steps.end();
  },
  end: async () => {
    rl.close();
  },
};

// Start the program by running the first step.
steps.start();

【讨论】:

  • 非常感谢,这正是我所需要的!!我对异步函数相当陌生,但您的示例有助于我理解使用它们
【解决方案2】:

rl.prompt() 方法将 readline.Interface 实例配置的提示写入输出中的新行,以便为用户提供提供输入的新位置。当用户输入“否”来询问不同的问题时使用 setPrompt。

const readline = require('readline');
let lastAnswer = '';
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
    prompt: 'Would you like to see which cars are available? Please type yes/no: '
});
rl.prompt();
rl.on('line', (line) => {
    switch (line.trim()) {
       case 'yes':
           lastAnswer = 'yes';
           console.log('great!');
           rl.setPrompt('Would you like to see which cars are available? Please type yes/no: ');
           break;
       case 'no':
           if (lastAnswer === 'no') {
               lastAnswer = '';
               rl.close();
           }
           lastAnswer = 'no';
           rl.setPrompt('Would you like to search by latitude or longitude instead? If yes, please type latitude and longitude: ');
           break;
       default:
           lastAnswer = '';
           console.log(`Say what? I might have heard '${line.trim()}'`);
           break;
    }
    rl.prompt();
}).on('close', () => {
    console.log('Have a great day!');
    process.exit(0);
});

【讨论】:

  • 感谢您的示例,但是如果用户在第二个问题中输入“否”,则该语句将重新询问用户相同的问题(纬度/经度),我该如何让用户退出如果他输入两次否?
  • 你可以使用变量保存最后一个答案,在代码中查看我的更新。
【解决方案3】:

question 函数需要回调函数,否则将被忽略。 所以你需要做的就是解决你的问题是添加一个回调函数到 rl.question 因为这是获得答案的唯一方法,您想知道答案吗?

rl.question('...?', function(){});

https://github.com/nodejs/node/blob/master/lib/readline.js#L270

来自 Node.js 源代码:

Interface.prototype.question = function(query, cb) {
  if (typeof cb === 'function') {
    if (this._questionCallback) {
      this.prompt();
    } else {
      this._oldPrompt = this._prompt;
      this.setPrompt(query);
      this._questionCallback = cb;
      this.prompt();
    }
  }
};

【讨论】:

    【解决方案4】:

    如果你还没有使用 readline 包,[Inquirer][1] 是一个非常好的 npm 库,它支持使用 Promise。例如

    var inquirer = require('inquirer');
    inquirer.prompt([
      {
        type: 'confirm',
        name: 'whichCar',
        message: 'Which car do you want to drive?'
      }
    ]).then(function(response) {
       if (response.whichCar === true) {
          // do your thing
       } else { 
          // do your second prompt
       }
    })
    

    如果你必须使用 readline,那么上面的用户已经很好地解释了回调是如何工作的。如果不是,那么我认为查询器是一个强大的选择,具有很大的灵活性和定制性。 [1]:https://www.npmjs.com/package/inquirer/v/0.3.5

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-05
      • 2018-06-08
      • 2017-01-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多