最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Using readline in Node.js - Stack Overflow

programmeradmin0浏览0评论

I'm trying to use readline inside an else if statement:

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();
});

What is the correct way to ask the user a different question if the user types 'No'?

Currently, if the user types No, the second question does not get asked.

I'm trying to use readline inside an else if statement:

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();
});

What is the correct way to ask the user a different question if the user types 'No'?

Currently, if the user types No, the second question does not get asked.

Share Improve this question edited Mar 19, 2020 at 14:49 Molda 5,7042 gold badges25 silver badges41 bronze badges asked Oct 11, 2018 at 18:39 SaraSara 851 gold badge1 silver badge5 bronze badges 1
  • I'm just wondering if you learnt what was wrong with your code since you accepted an answer that doesn't actually answer your question? – Molda Commented Oct 12, 2018 at 13:12
Add a comment  | 

4 Answers 4

Reset to default 10

If I were to do this I would start by making a promise based version of the readLine question function:

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

And I would structure it as a set of steps:

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();
  },
};

If you're new to async functions note that you have to type await before your question to instruct node not to proceed until the question resolves with an answer.

Also note that whenever we change steps you need to return so that the rest of the step doesn't run.

Here is the complete program for you to copy and play with:

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();

The rl.prompt() method writes the readline.Interface instances configured prompt to a new line in output in order to provide a user with a new location at which to provide input. Using setPrompt when the user typing 'no' to ask the different question.

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);
});

The question function requires a callback function otherwise it is ignored. So all you need to do to fix your problem is to add a callback function to the rl.question because that's the only way to get the answer and you want to know the answer right?

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

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

From Node.js source:

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();
    }
  }
};

If you are not married to the readline package, [Inquirer][1] is a very nice npm library that supports use of promises. E.G.

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
   }
})

If you must used readline, then the above users have explained very well how the callbacks need to work. If not, then I think inquirer is a strong option with lots of flexibility and customization. [1]: https://www.npmjs.com/package/inquirer/v/0.3.5

发布评论

评论列表(0)

  1. 暂无评论