【问题标题】:Node.js synchronous promptNode.js 同步提示
【发布时间】:2012-08-16 01:42:11
【问题描述】:

我将 prompt library 用于 Node.js,并且我有以下代码:

var fs = require('fs'),
    prompt = require('prompt'),
    toCreate = toCreate.toLowerCase(),
    stats = fs.lstatSync('./' + toCreate);

if(stats.isDirectory()){
    prompt.start();
    var property = {
        name: 'yesno',
        message: 'Directory esistente vuoi continuare lo stesso? (y/n)',
        validator: /y[es]*|n[o]?/,
        warning: 'Must respond yes or no',
        default: 'no'
    };
    prompt.get(property, function(err, result) {                
        if(result === 'no'){
            console.log('Annullato!');
            process.exit(0);
        }
    });
}
console.log("creating ", toCreate);
console.log('\nAll done, exiting'.green.inverse);

如果显示提示,它似乎不会阻止代码执行,但会继续执行,并显示控制台的最后两条消息,而我仍然需要回答问题。

有没有办法让它阻塞?

【问题讨论】:

    标签: node.js prompt


    【解决方案1】:

    由于 Node 中的 IO 不会阻塞,因此您不会找到一种简单的方法来使这样的事情同步。相反,您应该将代码移动到回调中:

      ...
    
      prompt.get(property, function (err, result) {               
        if(result === 'no'){
            console.log('Annullato!');
            process.exit(0);
        }
    
        console.log("creating ", toCreate);
        console.log('\nAll done, exiting'.green.inverse);
      });
    

    或者提取它并调用提取的函数:

      ...
    
      prompt.get(property, function (err, result) {               
        if(result === 'no'){
            console.log('Annullato!');
            process.exit(0);
        } else {
            doCreate();
        }
      });
    
      ...
    
    function doCreate() {
        console.log("creating ", toCreate);
        console.log('\nAll done, exiting'.green.inverse);
    }
    

    【讨论】:

    • 如果意味着很多问题?
    • Node.js 本质上是异步的。如果这对于您的特定应用程序来说不是一个好的范例,那么 Node 可能不是该特定用例的正确技术选择。你真的必须愿意接受框架的异步特性(流控制库等工具和函数生成器等模式有很大帮助)。
    • 我对代码进行了一些重构,在大多数情况下真的很喜欢 nodejs 非阻塞 i/o,但现在我正在尝试构建一个小型命令行实用程序,但由于它遇到了一些问题许多(如果不是全部)操作都应遵循脚本这一部分中的顺序,并且并非总是可以使用回调。你知道什么好的流控制库或模式吗?
    • 我也有类似的情况,正在尝试创建一个类似于Thor's actions 的Node 工具。我真的很喜欢async 库; serieswaterfall 可能对这个特定任务特别有用。
    • 在搞砸之后,我不确定 async 是否真的有帮助。看看这个要点,看看它是否有意义:gist.github.com/77ce3468303351c06f29
    【解决方案2】:

    不幸的是,使用 flatiron 的提示库,没有办法阻止代码。但是,我可能会建议我自己的 sync-prompt 库。顾名思义,它允许您同步提示用户输入。

    有了它,你只需发出一个函数调用,然后取回用户的命令行输入:

    var prompt = require('sync-prompt').prompt;
    
    var name = prompt('What is your name? ');
    // User enters "Mike".
    
    console.log('Hello, ' + name + '!');
    // -> Hello, Mike!
    
    var hidden = true;
    var password = prompt('Password: ', hidden);
    // User enters a password, but nothing will be written to the screen.
    

    如果你愿意,不妨试一试。

    记住:不要在网络应用程序上使用它。它应该只用于命令行应用程序。

    更新:根本不要使用这个库。坦率地说,这完全是个笑话。

    【讨论】:

    • 无法在 Ubuntu 14.04 上安装。 node-gyp rebuild
    • 最好使用 prompt-sync,它不需要 C++ 绑定并且适用于所有系统
    【解决方案3】:

    Vorpal.js 是我最近发布的一个库。它提供了具有交互式提示的同步命令执行,就像您要求的那样。以下代码将满足您的要求:

    var vorpal = require('vorpal')();
    
    vorpal.command('do sync')
      .action(function (args) {
        return 'i have done sync';
      });
    

    如上,一秒后提示将返回(仅在调用回调后)。

    【讨论】:

    • 看起来不太同步。
    • 哇,我一定是脑残了。我展示了一个异步示例而不是同步示例。我进行了编辑以包含同步版本。
    【解决方案4】:

    老问题,我知道,但我刚刚找到了完美的工具。 readline-sync 为您提供了一种在节点脚本中收集用户输入的同步方式。

    它使用起来非常简单,并且不需要任何依赖项(由于 gyp 问题,我无法使用同步提示)。

    来自 github 自述文件:

    var readlineSync = require('readline-sync');
    
    // Wait for user's response.
    var userName = readlineSync.question('May I have your name? ');
    console.log('Hi ' + userName + '!');
    

    我与这个项目没有任何关系,但它让我很开心,所以我不得不分享。

    【讨论】:

      【解决方案5】:

      我遇到过这个帖子和所有解决方案:

      • 实际上不提供同步提示解决方案
      • 已过时,不适用于新版本的节点。

      因此我创建了syncprompt .使用npm i --save syncprompt 安装它,然后添加:

      var prompt = require('syncprompt');
      

      例如,这将允许您这样做:

      var name = prompt("Please enter your name? ");
      

      还支持提示输入密码:

      var topSecretPassword = prompt("Please enter password: ", true);
      

      【讨论】:

      • 我实际上是在没有可用 python 的环境中工作,这也失败了。
      【解决方案6】:

      从 Node.js 8 开始,您可以使用 async/await 执行以下操作:

      const readline = require('readline');
      
      const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout
      });
      
      function readLineAsync(message) {
        return new Promise((resolve, reject) => {
          rl.question(message, (answer) => {
            resolve(answer);
          });
        });
      } 
      
      // Leverages Node.js' awesome async/await functionality
      async function demoSynchronousPrompt() {
        var promptInput = await readLineAsync("Give me some input >");
        console.log("Won't be executed until promptInput is received", promptInput);
        rl.close();
      }
      

      【讨论】:

      • 很好的答案。谢谢
      【解决方案7】:

      这是无依赖、同步的,适用于 Windows、Linux 和 OSX:

      // Synchronously prompt for input
      function prompt(message)
      {
          // Write message
          process.stdout.write(message);
      
          // Work out shell command to prompt for a string and echo it to stdout
          let cmd;
          let args;
          if (os.platform() == "win32")
          {
              cmd = 'cmd';
              args = [ '/V:ON', '/C', 'set /p response= && echo !response!' ];
          }
          else
          {
              cmd = 'bash';
              args = [ '-c', 'read response; echo "$response"' ];
          }
      
          // Pipe stdout back to self so we can read the echoed value
          let opts = { 
              stdio: [ 'inherit', 'pipe', 'inherit' ],
              shell: false,
          };
      
          // Run it
          return child_process.spawnSync(cmd, args, opts).stdout.toString().trim();
      }
      

      【讨论】:

        【解决方案8】:
        const buffer = Buffer.alloc(1024);
        require("fs").readSync(process.stdin.fd, buffer);
        console.log(buffer.toString());
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-05-11
          • 2015-02-23
          • 1970-01-01
          • 2016-06-02
          • 2015-09-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多