Node.js synchronous prompt

眉间皱痕 提交于 2019-12-23 07:57:39

问题


I'm using the prompt library for Node.js and I have this code:

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

If the prompt is show it seems that it doesn't block code execution but the execution continues and the last two messages by the console are shown while I still have to answer the question.

Is there a way to make it blocking?


回答1:


Since IO in Node doesn't block, you're not going to find an easy way to make something like this synchronous. Instead, you should move the code into the callback:

  ...

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

or else extract it and call the extracted function:

  ...

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



回答2:


With flatiron's prompt library, unfortunately, there is no way to have the code blocking. However, I might suggest my own sync-prompt library. Like the name implies, it allows you to synchronously prompt users for input.

With it, you'd simply issue a function call, and get back the user's command line input:

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.

So give it a try, if you'd like.

Bear in mind: DO NOT use this on web applications. It should only be used on command line applications.




回答3:


Since Node.js 8, you can do the following using 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(expenses) {
  var promptInput = await readLineAsync("Give me some input >");
  console.log("Won't be executed until promptInput is received", promptInput);
  rl.close();
}



回答4:


Old question, I know, but I just found the perfect tool for this. readline-sync gives you a synchronous way to collect user input in a node script.

It's dead simple to use and it doesn't require any dependencies (I couldn't use sync-prompt because of gyp issues).

From the github readme:

var readlineSync = require('readline-sync');

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

I'm not affiliated with the project in any way, but it just made my day, so I had to share.




回答5:


I've come across this thread and all the solutions either:

  • Don't actually provide a syncronous prompt solution
  • Are outdated and don't work with new versions of node.

And for that reason I have created syncprompt . Install it with npm i --save syncprompt and then just add:

var prompt = require('syncprompt');

For example, this will allow you to do:

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

It also supports prompting for passwords:

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



回答6:


Vorpal.js is a library I made that has just recently been released. It provides synchronous command execution with an interactive prompt, like you are asking. The below code will do what you are asking:

var vorpal = require('vorpal')();

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

With the above, the prompt will come back after a second is up (only after callback is called).



来源:https://stackoverflow.com/questions/12042534/node-js-synchronous-prompt

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!