如何在Node.js中无限读取

use*_*477 8 nonblocking node.js

while(1){
    rl.question("Command: ",function(answer){
    console.log(answer);
    })
}
Run Code Online (Sandbox Code Playgroud)

刚刚尝试了这段代码,但是逐个输入,它会使"Command:"行闪烁.我知道node.js是非阻塞的,但我不知道如何解决这个问题.

myn*_*iil 19

var readline = require('readline');
var log = console.log;

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

var recursiveAsyncReadLine = function () {
  rl.question('Command: ', function (answer) {
    if (answer == 'exit') //we need some base case, for recursion
      return rl.close(); //closing RL and returning from function.
    log('Got it! Your answer was: "', answer, '"');
    recursiveAsyncReadLine(); //Calling this function again to ask new question
  });
};

recursiveAsyncReadLine(); //we have to actually start our recursion somehow
Run Code Online (Sandbox Code Playgroud)

关键是不要使用同步循环.我们应该rl.question在处理完答案后才问下.递归是要走的路.我们定义函数,询问问题并处理答案,然后在答案处理后从内部调用它.这样我们就开始了,就像常规循环一样.但循环不关心ansyc代码,而我们的实现关心.

  • 这可以工作但是每次输入命令时都会添加一个新的调用堆栈,因此如果输入的命令太多,可能会达到堆栈溢出.是不是有使用rl.question()的常量堆栈解决方案? (6认同)
  • 它不会每次@Javarome 都向堆栈添加调用:每次执行 `recursiveAsyncReadLine()` 都会打印问题,注册回调并立即结束。`recursiveAsyncReadLine()` 由回调函数调用,而不是由它自己调用。您可以通过在每次调用时打印堆栈来验证它:`const stack = new Error().stack; 控制台日志(堆栈);` (4认同)

nwa*_*yve 17

通过Node.js文档的另一个选择是使用事件:

var readline = require('readline'),
    rl = readline.createInterface(process.stdin, process.stdout);

rl.setPrompt('OHAI> ');
rl.prompt();

rl.on('line', function(line) {
    switch(line.trim()) {
        case 'hello':
            console.log('world!');
            break;
        default:
            console.log('Say what? I might have heard `' + line.trim() + '`');
        break;
    }
    rl.prompt();
}).on('close', function() {
    console.log('Have a great day!');
    process.exit(0);
});
Run Code Online (Sandbox Code Playgroud)


Kon*_*rin 6

这是使用异步生成器函数的版本:

async function* questions(query: string) {
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });

  try {
    for (;;) {
      yield new Promise((resolve) => rl.question(query, resolve));
    }
  } finally {
    rl.close();
  }
}
Run Code Online (Sandbox Code Playgroud)

可以与for wait...of 一起使用,如下所示:

async function run() {
  for await (const answer of questions("Command: ")) {
    console.log(`I heard ${answer}`);
    if (answer == "done") break;
  }
}

run(); // For the sake of example, start the async function at the top level of nodejs script
Run Code Online (Sandbox Code Playgroud)