如何读取用户输入 Node.js - 使用 Promises 重构

Jef*_*f B 3 javascript command-line node.js promise

请阅读这篇非常简短的文章,以了解我正在尝试做的事情。

主要的一点是,正如作者所说,我“需要问用户几个问题,......验证输入数据并在输入错误时重新提问。” 此外,除了根据正则表达式检查输入之外,我可能需要做更复杂的事情来验证输入。例如,检查以确保当前输入不是由用户在较早的提示下输入的。

我有兴趣重构本文中的主要代码片段,使其基于 Promise。我想这样做的一个明显原因是,在我需要提示用户超过两三次的情况下,避免回调地狱。你对如何重构这个有什么建议吗?令我失望的是对 的递归调用ask(),以及如果承诺失败,就是这样:它完成了。而这段代码需要一遍又一遍地循环,直到获得有效输入。所以我什至不知道从哪里开始。

另外,如果您有任何“gordian 结”类型的解决方案,我愿意朝着完全不同的方向前进。也许 Node 有一个内置的库来做这种我不知道的事情?也许readline?我不知道,因为我对这些东西太陌生了,而且readlineAPI 对我来说并没有多大意义......

基本上,如果您能想到任何重构方法,这样我就不必陷入回调噩梦中,我将不胜感激:)

无论如何,这是完整的代码片段:

function ask(question, format, callback) {
 var stdin = process.stdin, stdout = process.stdout;

 stdin.resume();
 stdout.write(question + ": ");

 stdin.once('data', function(data) {
   data = data.toString().trim();

   if (format.test(data)) {
     callback(data);
   } else {
     stdout.write("It should match: "+ format +"\n");
     ask(question, format, callback);
   }
 });
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*lms 5

首先,promisify stdin 阅读器:

function askOnce(question){
  var stdin = process.stdin, stdout = process.stdout;

  stdin.resume();
  stdout.write(question + ": ");

  return new Promise(res => {
    stdin.once('data', function(data) {
      res(data.toString().trim());
    });
  });
}
Run Code Online (Sandbox Code Playgroud)

所以没有问是容易的:

async function ask(question, format){
  let answer;

  do {
    answer = await askOnce(question);
  } while(!answer.test(format));

  return answer;
}
Run Code Online (Sandbox Code Playgroud)

没有async / await它有点丑(使用递归和承诺展平机制):

 function ask(question, format){
   return askOnce(question).then(answer =>  {
      if(!answer.test(format))
         return ask(question, format);
      return answer;
  });
}
Run Code Online (Sandbox Code Playgroud)