Чтение значения из консоли, интерактивно
Я думал сделать простой сервер http server с некоторым расширением консоли. Я нашел фрагмент для чтения из данных командной строки.
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();
});
ну, чтобы задать вопросы повторно, я не могу просто использовать while(done) { } петли? Также хорошо, если сервер получает вывод во время вопроса, он разрушает линию.
7 ответов:
вы не можете сделать цикл" while(done)", потому что это потребует блокировки на входе, что-то узел.Джей не любит этого делать.
вместо этого установите обратный вызов, который будет вызываться каждый раз, когда что-то вводится:
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() + "]"); });
я использовал другой API для этой цели..
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); });Это позволяет запрашивать в цикле, пока ответ не будет
right. Также это дает приятную маленькую консоль.Вы можете найти подробности @ http://nodejs.org/api/readline.html#readline_example_tiny_cli
API Readline сильно изменился с 12'. Документ показывает полезный пример для захвата пользовательского ввода из стандартного потока:
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(); });
пожалуйста, используйте readline-sync, это позволяет работать с синхронной консолью без обратных вызовов hells. Даже работает с паролями:
var favFood = read.question('What is your favorite food? ', { hideEchoBack: true // The typed text on screen is hidden by `*` (default). });
@rob ответ будет работать в большинстве случаев, но это может не работать, как вы ожидаете с длинными входами.
это то, что вы должны вместо этого использовать:
const stdin = process.openStdin(); let content = ''; stdin.addListener('data', d => { content += d.toString(); }); stdin.addListener('end', () => { console.info(`Input: ${content}`); });объяснение, почему это решение работает:
addListener('data')работает как буфер, обратный вызов будет вызван, когда он заполнен или/и его конец ввода.как насчет длинных входов? Один
'data'обратного вызова будет недостаточно, поэтому вы получите свой вход разделен на две или больше деталей. Это часто не удобно.
addListener('end')сообщит нам, когда считыватель stdin закончит чтение нашего ввода. Поскольку мы хранили предыдущие данные, теперь мы можем читать и обрабатывать их все вместе.
Я считаю, что это заслуживает современный
async-awaitответ, предполагая, что узел >= 7.использовать X-это.ответа по-прежнему использует
ReadLine::questionно обертывает его так, чтоwhile (done) {}возможно, что-то, о чем ОП спрашивает явно.var cl = readln.createInterface( process.stdin, process.stdout ); var question = function(q) { return new Promise( (res, rej) => { cl.question( q, answer => { res(answer); }) }); };а затем пример использования
(async function main() { var answer; while ( answer != 'yes' ) { answer = await question('Are you sure? '); } console.log( 'finally you are sure!'); })();приводит к следующему разговору
Are you sure? no Are you sure? no Are you sure? yes finally you are sure!
общий случай использования, вероятно, будет для приложения отображать общее приглашение и обрабатывать его в инструкции switch.
вы можете получить поведение, эквивалентное циклу while, используя вспомогательную функцию, которая будет вызывать себя в обратном вызове:
const readline = require('readline'); const rl = readline.createInterface(process.stdin, process.stdout); function promptInput (prompt, handler) { rl.question(prompt, input => { if (handler(input) !== false) { promptInput(prompt, handler); } else { rl.close(); } }); } promptInput('app> ', input => { switch (input) { case 'my command': // handle this command break; case 'exit': console.log('Bye!'); return false; } });вы можете передать пустую строку вместо
'app> 'если ваше приложение уже печатает что-то на экране за пределами этого цикла.
Comments