在 Node.js 中使用 readline

Using readline in Node.js

我正在尝试在 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();
});

如果用户键入 'No',向用户询问不同问题的正确方法是什么?

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

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

rl.prompt() 方法将 readline.Interface 实例配置提示写入输出中的新行,以便为用户提供提供输入的新位置。当用户键入 'no' 以询问不同的问题时使用 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);
});

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

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,那么上面的用户已经很好地解释了回调需要如何工作。如果没有,那么我认为 inquirer 是一个强大的选择,具有很大的灵活性和定制性。 [1]: https://www.npmjs.com/package/inquirer/v/0.3.5

如果我要这样做,我会首先制作一个基于承诺的 readLine 问题函数版本:

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