Node.js无限循环函数,退出某些用户输入

时间:2014-06-12 10:25:22

标签: javascript node.js

我不太了解节点在异步和循环方面的工作原理。 我想在这里实现的是让控制台打印出“ Command:”并等待用户的输入。但是在等待的时候,我希望它无休止地运行“ someRandomFunction()”,直到用户输入“退出”到终端上。

非常感谢所有的帮助 - 可能还有一个解释,所以我能理解!

谢谢! :)

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

2 个答案:

答案 0 :(得分:4)

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

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

我不确定您用于.question的语法是否正确,但代码的这部分是否有效?

你也可以用以下方式写这个。

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

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

这里的重要教训是,要重新使用一个函数,必须对其进行命名并在范围内可用。如果您对此有任何疑问,请询问。

答案 1 :(得分:0)

另一个答案很好,但不必要使用递归。

解决这个问题的关键是,在您看来,将其他语言中使用的基于循环的简单方法与Node的异步方法分开。

在其他语言中,您可以使用如下循环:

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

至少使用Readline的节点无法通过这种方式工作。

在Node中,启动Readline,为其提供事件处理程序,然后然后返回,并处理readline循环以后的完成。

考虑以下代码,您可以复制并粘贴并运行该代码(如果您执行yarn add readlinenpm install 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风格:

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

请注意,由于某种原因,我添加了输出“ replDemo已被调用”-运行上面的命令将显示如下输出:

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

请注意在第一个“ ready>”提示后立即出现“ replDemo的调用方式”。这是因为replDemo()函数立即返回,然后run2()立即退出,并且main已完成-但readline仍在执行!

如果您来自像我这样的当务之急的编程背景,这很难理解。 nodejs核心的异步事件驱动循环一直保持运行,直到完成所有工作为止,并且在最后一个promise发生时发生,这种情况发生在readline实例“关闭”时发生,而在输入“ exit”时发生用户(或收到EOF,在大多数系统上为CTRL + D,在Windows上为CTRL + Z)。