反复提示用户,直到使用nodeJS async-await解析

sir*_*ain 6 javascript asynchronous node.js async-await

我尝试向用户重复询问问题,直到他们使用此代码给出正确的答案.

问题是,如果用户第一次没有给出正确的答案,它将无法解决.

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

function promptAge() {
    return new Promise(function(resolve){
        rl.question('How old are you? ', function(answer) {
            age = parseInt(answer);
            if (age > 0) {
                resolve(age);
            } else {
                promptAge();
            }
        });
    });
}

(async function start() {
    var userAge =  await promptAge();
    console.log('USER AGE: ' + userAge);
    process.exit();
})();
Run Code Online (Sandbox Code Playgroud)

以下是每种情况的终端输出:

当用户第一次给出正确答案时,它很好......

How old are you? 14
USER AGE: 14
Run Code Online (Sandbox Code Playgroud)

当用户给出了错误的答案时,它被卡住了(不会解决,处理也不会退出)......

How old are you? asd
How old are you? 12
_
Run Code Online (Sandbox Code Playgroud)

当用户没有给出任何答案时,它也被卡住了......

How old are you? 
How old are you? 
How old are you? 12
_
Run Code Online (Sandbox Code Playgroud)

任何人都可以解释发生的事情,或者给我一些解释这种性质的文章/视频吗?

顺便说一下,我尝试使用async/await进行学习(尝试学习如何异步处理).我已经尝试过没有async/await(promptAge()不返回任何承诺)并且没关系.

感谢您的关注.

drj*_*976 5

parseInt()尽管 skellertor 建议良好做法,但与此无关。

问题是每次promptAge()调用时都会生成一个新的 Promise - 但原始调用者即start()只有第一个 Promise 的可见性。如果您输入了错误的输入,promptAge()则会生成一个新的 Promise(在从未解析的 Promise 中)并且您的成功代码将永远不会运行。

为了解决这个问题,只生成一个 Promise。有更优雅的方法可以做到这一点,但为了清楚起见,并避免将代码破解成无法识别的东西......

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

// the only changes are in promptAge()
// an internal function executes the asking, without generating a new Promise
function promptAge() {
  return new Promise(function(resolve, reject) {
    var ask = function() {
      rl.question('How old are you? ', function(answer) {
        age = parseInt(answer);
        if (age > 0) {
          // internal ask() function still has access to resolve() from parent scope
          resolve(age, reject);
        } else {
          // calling ask again won't create a new Promise - only one is ever created and only resolves on success
          ask();
        }
      });
    };
    ask();
  });
}

(async function start() {
    var userAge =  await promptAge();
    console.log('USER AGE: ' + userAge);
    process.exit();
})();
Run Code Online (Sandbox Code Playgroud)

  • 很高兴你发现它有用。试图避免从根本上更改您的代码,以便您可以理解这个概念 - 但它非常好,只是错过了一件至关重要的事情。你的后续问题的答案是一种风格 - 传递 `resolve()` 作为参数会起作用,但不是好的做法。这是一个闭包的例子,孩子们保留对父值的访问权,恕我直言,这是更好的模式,更清晰,是自包含的。 (2认同)
  • 不要低估你在那里建造的东西——你会学到很多工作要做一些真实的事情,并解决现实世界的问题,不管它看起来多么微不足道。比教程好多了!要获得所有这些东西,请在进入 Promises 和 async/await 之前专注于理解回调。回调是异步编程的本质,花几个小时来真正掌握它们将带来巨大的回报。这是面向节点的,但很好读(来自第三段。)https://github.com/maxogden/art-of-node (2认同)