171 votes

Lecture interactive d'une valeur à partir de la console

J'ai pensé à faire un simple serveur http avec une extension de console. J'ai trouvé le snippet pour lire les données de la ligne de commande.

  var i = rl.createInterface(process.stdin, process.stdout, null);
  i.question('Write your name: ', function(answer) {
    console.log('Nice to meet you> ' + answer);
    i.close();
    process.stdin.destroy();

  });

Pour poser les questions de manière répétée, je ne peux pas simplement utiliser la fonction while(done) { } boucle ? De même, si le serveur reçoit une sortie au moment de la question, cela ruine la ligne.

6 votes

Je suppose qu'en rl vous voulez dire ligne de lecture ?

0 votes

Vous pouvez utiliser une interface non bloquante comme celle utilisée dans cette réponse , vous pouvez alors faire un while(done) boucle.

195voto

rob Points 3743

Vous ne pouvez pas faire une boucle "while(done)" car cela nécessiterait de bloquer l'entrée, ce que node.js n'aime pas faire.

Au lieu de cela, mettez en place une procédure de rappel qui sera appelée à chaque fois qu'un élément est saisi :

var stdin = process.openStdin();

stdin.addListener("data", function(d) {
    // note:  d is an object, and when converted to a string it will
    // end with a linefeed.  so we (rather crudely) account for that  
    // with toString() and then trim() 
    console.log("you entered: [" + 
        d.toString().trim() + "]");
  });

2 votes

Merci cela fonctionne, est-ce que le listener "end" permet d'appeler des opérations de fermeture et de dire 'Goodbye' ?

0 votes

J'ai supprimé l'écouteur "end" de l'exemple, je ne sais pas où il sera vraiment utile pour être honnête.

0 votes

Comment contrôler les données typées avec l'instruction if ? ou swtich case ?

121voto

Madhan Points 555

J'ai utilisé un autre API à cette fin

var readline = require('readline');
var rl = readline.createInterface(process.stdin, process.stdout);
rl.setPrompt('guess> ');
rl.prompt();
rl.on('line', function(line) {
    if (line === "right") rl.close();
    rl.prompt();
}).on('close',function(){
    process.exit(0);
});

Cela permet d'inviter en boucle jusqu'à ce que la réponse soit right . Vous pouvez trouver les détails sur le site @ http://nodejs.org/api/readline.html#readline_example_tiny_cli

16 votes

C'est une excellente réponse. Ce qui n'est peut-être pas évident (mais qui est un gros plus), c'est que readline n'est pas une dépendance externe : Il fait partie de node.js.

0 votes

J'obtiens Uncaught ReferenceError : "Whatever I wrote" n'est pas défini.

53voto

Patrick.SE Points 1601

L'API Readline a beaucoup changé depuis la version 12'. La documentation montre un exemple utile pour capturer l'entrée de l'utilisateur à partir d'un flux standard :

const readline = require('readline');

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

rl.question('What do you think of Node.js? ', (answer) => {
  console.log('Thank you for your valuable feedback:', answer);
  rl.close();
});

Plus d'informations ici.

7 votes

Il ne s'agit que d'un exemple élémentaire. Comment interagir ? question/réponse ? choix multiples et autres ? Comment rouvrir le rl une fois fermé, si ce n'est pas possible comment travailler avec le rl ouvert pour interagir avec l'utilisateur en incluant une certaine logique ?

0 votes

Comment stocker la valeur de la réponse si nous voulons l'utiliser dans une autre fonction ?

0 votes

@Infinity Je pense que c'est un peu tard mais vous pouvez envelopper le code ci-dessus dans une fonction qui renvoie une promesse qui se résout en réponse. Avec cela, vous pouvez utiliser la syntaxe async-await pour utiliser facilement la valeur de answer et la stocker ou l'utiliser dans d'autres fonctions.

45voto

Wiktor Zychla Points 23918

Je pense que cela mérite un traitement moderne async-await réponse, en supposant qu'un nœud >= 7.x est utilisé.

La réponse utilise toujours ReadLine::question mais l'enveloppe de manière à ce que le while (done) {} est possible, ce que l'OP demande explicitement.

var cl = readln.createInterface( process.stdin, process.stdout );
var question = function(q) {
    return new Promise( (res, rej) => {
        cl.question( q, answer => {
            res(answer);
        })
    });
};

puis un exemple d'utilisation

(async function main() {
    var answer;
    while ( answer != 'yes' ) {
        answer = await question('Are you sure? ');
    }
    console.log( 'finally you are sure!');
})();

conduit à la conversation suivante

Are you sure? no
Are you sure? no
Are you sure? yes
finally you are sure!

Editer . Pour terminer correctement l'entrée, appelez

cl.close();

à la fin du script.

3 votes

C'est exactement la réponse que je cherchais. Je pense qu'elle devrait être la première.

2 votes

Très belle. Async await est nécessaire pour les grands scripts. C'est exactement ce dont j'avais besoin.

0 votes

Concis. Mais la saisie est toujours interrompue, elle ne se termine pas. Même après avoir appuyé sur Entrée, la console reste bloquée. En appuyant sur ctrl-c ou ctrl-d, elle repart. Que manque-t-il ?

23voto

Arango Points 259

Veuillez utiliser synchronisation en ligne Cela vous permet de travailler avec une console synchrone sans callbacks. Il fonctionne même avec les mots de passe :

var favFood = read.question('What is your favorite food? ', {
  hideEchoBack: true // The typed text on screen is hidden by `*` (default). 
});

5 votes

Cela nécessite une dépendance supplémentaire et je préférerais donc d'autres solutions.

0 votes

Ne s'exécute pas sur SO "Uncaught ReferenceError : read is not defined" (Erreur de référence non résolue : la lecture n'est pas définie)

0 votes

L'extrait de code génère une erreur

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X