Node.js无限循环功能,在某些用户输入时退出

xxb16uws  于 2023-06-22  发布在  Node.js
关注(0)|答案(3)|浏览(147)

我不太明白node在异步和循环方面是如何工作的。我想在这里实现的是让控制台打印出“Command:”并等待用户的输入。但是在等待过程中,我希望它无休止地运行“someRandomFunction()”,直到用户在终端上输入“exit”。
将感谢所有的帮助-和可能的解释,所以我可以理解!
Thank you!:)

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

rl.question("Command: ", function(answer) {
    if (answer == "exit"){
        rl.close();
    } else {
        // If not "exit", How do I recall the function again?
    }
});

someRandomFunction();
zqry0prt

zqry0prt1#

我建议像这样使函数可重复。

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

var waitForUserInput = function() {
  rl.question("Command: ", function(answer) {
    if (answer == "exit"){
        rl.close();
    } else {
        waitForUserInput();
    }
  });
}

那就打电话

waitForUserInput();
someRandomFunction();

我不确定你使用的语法是否正确。问题是,这部分代码工作吗?
你也可以用下面的方式写。

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

function waitForUserInput() {
  rl.question("Command: ", function(answer) {
    if (answer == "exit"){
        rl.close();
    } else {
        waitForUserInput();
    }
  });
}

这里的重要教训是,要重用一个函数,它必须被命名并在作用域中可用。如果您对此有任何疑问,请提问。

q8l4jmvw

q8l4jmvw2#

另一个答案是好的,但不必要地使用了递归。
解决这个问题的关键是,在你看来,将其他语言中使用的基于循环的简单方法与Node的异步方法分开。
在其他语言中,你可以使用这样的循环:

while not finished:
  line = readline.read() 
  if line == 'woof':
    print('BARK')
  elif line == 'exit':
    finished = True
  ... # etc

Node,至少在Readline中,不是这样工作的。
在Node中,您启动Readline,给它事件处理程序,* 然后返回 *,并处理readline循环的完成 * 稍后 *。
考虑以下代码,您可以复制-粘贴-运行:

const readline = require('readline');

function replDemo() {
  return new Promise(function(resolve, reject) {
    let rl = readline.createInterface(process.stdin, process.stdout)
    rl.setPrompt('ready> ')
    rl.prompt();
    rl.on('line', function(line) {
      if (line === "exit" || line === "quit" || line == 'q') {
        rl.close()
        return // bail here, so rl.prompt() isn't called again
      }

      if (line === "help" || line === '?') {
        console.log(`commands:\n  woof\n  exit|quit\n`)
      } else if (line === "woof") {
        console.log('BARK!')
      } else if (line === "hello") {
        console.log('Hi there')
      } else {
        console.log(`unknown command: "${line}"`)
      }
      rl.prompt()

    }).on('close',function(){
      console.log('bye')
      resolve(42) // this is the final result of the function
    });
  })
}

async function run() {
  try {
    let replResult = await replDemo()
    console.log('repl result:', replResult)

  } catch(e) {
    console.log('failed:', e)
  }
}

run()

运行这个命令,你会得到如下输出:

$ node src/repl-demo.js
ready> hello
Hi there
ready> boo
unknown command: "boo"
ready> woof
BARK!
ready> exit
bye
repl result: 42

请注意,run函数调用replDemo并“等待”promise的结果。
如果你不熟悉async/await,这里有一个同样的逻辑,它是用“传统”的Promise风格写的:

function run2() {
  replDemo().then(result => {
    console.log('repl result:', result)
  }).catch(e => {
    console.log('failed:', e)
  })
  console.log('replDemo has been called')
}

请注意,我添加了输出"replDemo has been called"是有原因的-运行上面的命令会显示如下输出:

$ node src/repl-demo.js
ready> replDemo has been called
woof
BARK!
ready> hello
Hi there
ready> bye
repl result: 42

注意"replDemo has been called"是如何在第一个"ready>"提示符之后立即出现的。这是因为replDemo()函数立即返回,然后run2()立即退出,main也完成了--但readline仍在执行!
如果你像我一样有命令式编程的背景,这很难理解。nodejs核心的异步事件驱动循环会一直运行,直到所有工作都完成,当最后一个promise被解析时,这会发生在readline示例被“关闭”时,这会发生在用户输入“exit”时(或者接收到EOF,在大多数系统上是CTRL + D,在Windows上是CTRL + Z)。

vuv7lop3

vuv7lop33#

到目前为止,我没有在答案中看到ES模块版本。这样做在两个方面更“干净”:
1.使用async(好吧,只是一个顶级的await)有助于避免回调或Promises/then()的不必要的“混乱”。是的,Node擅长异步执行,但这不是一个多用户Web服务器。它是同步Cmd-line终端用户输入用例。
1.更重要的是,它允许无限循环使用do-while(因为它应该是)而不是(讨厌的)递归。如果最终用户输入“退出”,则循环退出。
这段代码似乎比其他解决方案更合理:

import * as readline from 'node:readline/promises';
import { stdin as input, stdout as output } from 'node:process';

const rl = readline.createInterface({ input, output });

do {
    var answer = await rl.question('Enter something: ');
    if (answer === 'quit') break;
    console.log(`You entered: ${answer}`);
} while(true);

rl.close();

样本输出:

$ node inploop.mjs
Enter something: ok
You entered: ok
Enter something: here
You entered: here
Enter something: quit
$

相关问题