콘솔에서 대화형으로 값 읽기
나는 콘솔 확장 기능이 있는 간단한 서버 http 서버를 만들려고 생각했습니다.명령줄 데이터에서 읽을 스니펫을 찾았습니다.
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) { }
. ㅠㅠ? 또한 질문 시간에 서버가 출력을 받으면 라인을 망칩니다.
"while(done)" 루프는 node.js가 하기 싫어하는 입력을 차단해야 하기 때문에 수행할 수 없습니다.
대신 무언가가 입력될 때마다 호출되도록 콜백을 설정합니다.
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 에서 확인할 수 있습니다.
Readline API는 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();
});
난 이게 현대적인 가치가 있다고 믿습니다.async-await
노드 >= 7.x를 사용한다고 가정하면 응답합니다.
답은여전사다니용됩히다니▁uses를 합니다.ReadLine::question
하지만 그것을 포장해서 그것을.while (done) {}
OP가 명시적으로 질문하는 것은 가능합니다.
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!
편집. 입력을 올바르게 종료하려면,
cl.close();
대본의 마지막에.
readline-sync를 사용하십시오. 그러면 셸 콜백 없이 동기식 콘솔로 작업할 수 있습니다.암호로도 작동합니다.
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 리더가 우리의 입력을 다 읽었을 때 우리에게 알려줄 것입니다.이전 데이터를 저장했으므로 이제 모든 데이터를 함께 읽고 처리할 수 있습니다.
다음은 예입니다.
const stdin = process.openStdin()
process.stdout.write('Enter name: ')
stdin.addListener('data', text => {
const name = text.toString().trim()
console.log('Your name is: ' + name)
stdin.pause() // stop reading
})
출력:
Enter name: bob
Your name is: bob
Inquirer는 일반적인 대화형 명령줄 사용자 인터페이스 모음을 제공하므로 사용하는 것이 좋습니다.
const inquirer = require('inquirer');
const questions = [{
type: 'input',
name: 'name',
message: "What's your name?",
}];
const answers = await inquirer.prompt(questions);
console.log(answers);
이건 너무 복잡해요.보다 쉬운 버전:
var rl = require('readline');
rl.createInterface... etc
을 사용할 것입니다.
var rl = require('readline-sync');
그러면 사용할 때 대기합니다.
rl.question('string');
그러면 반복하기가 더 쉽습니다.예:
var rl = require('readline-sync');
for(let i=0;i<10;i++) {
var ans = rl.question('What\'s your favourite food?');
console.log('I like '+ans+' too!');
}
일반적인 사용 사례는 앱이 일반 프롬프트를 표시하고 스위치 문으로 처리하는 것입니다.
콜백에서 자신을 호출하는 도우미 기능을 사용하여 잠시 루프에 해당하는 동작을 얻을 수 있습니다.
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> '
앱이 이미 이 루프 외부의 화면에 무언가를 인쇄한 경우.
이에 대한 제 접근 방식은 비동기 생성기를 사용하는 것입니다.
일련의 질문이 있다고 가정합니다.
const questions = [
"How are you today ?",
"What are you working on ?",
"What do you think of async generators ?",
]
를 사용하려면await
키워드, 프로그램을 비동기 IIF로 래핑해야 합니다.
(async () => {
questions[Symbol.asyncIterator] = async function * () {
const stdin = process.openStdin()
for (const q of this) {
// The promise won't be solved until you type something
const res = await new Promise((resolve, reject) => {
console.log(q)
stdin.addListener('data', data => {
resolve(data.toString())
reject('err')
});
})
yield [q, res];
}
};
for await (const res of questions) {
console.log(res)
}
process.exit(0)
})();
예상 결과:
How are you today ?
good
[ 'How are you today ?', 'good\n' ]
What are you working on ?
:)
[ 'What are you working on ?', ':)\n' ]
What do you think about async generators ?
awesome
[ 'What do you think about async generators ?', 'awesome\n' ]
질문에 대한 답변을 모두 얻고자 하는 경우 간단한 수정을 통해 이를 달성할 수 있습니다.
const questionsAndAnswers = [];
for await (const res of questions) {
// console.log(res)
questionsAndAnswers.push(res)
}
console.log(questionsAndAnswers)
/*
[ [ 'How are you today ?', 'good\n' ],
[ 'What are you working on ?', ':)\n' ],
[ 'What do you think about async generators ?', 'awesome\n' ] ]
*/
저는 명령 줄에서 입력을 가져오는 노드에서 "tic-tac-toe" 게임을 작성해야 했고, 이 기본적인 비동기/대기 코드 블록을 작성해야 했습니다. 이 코드 블록이 그 역할을 했습니다.
const readline = require('readline')
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
async function getAnswer (prompt) {
const answer = await new Promise((resolve, reject) =>{
rl.question(`${prompt}\n`, (answer) => {
resolve(answer)
});
})
return answer
}
let done = false
const playGame = async () => {
let i = 1
let prompt = `Question #${i}, enter "q" to quit`
while (!done) {
i += 1
const answer = await getAnswer(prompt)
console.log(`${answer}`)
prompt = processAnswer(answer, i)
}
rl.close()
}
const processAnswer = (answer, i) => {
// this will be set depending on the answer
let prompt = `Question #${i}, enter "q" to quit`
// if answer === 'q', then quit
if (answer === 'q') {
console.log('User entered q to quit')
done = true
return
}
// parse answer
// if answer is invalid, return new prompt to reenter
// if answer is valid, process next move
// create next prompt
return prompt
}
playGame()
읽기 라인 차단 해제 동작 차단 중
이제 리드라인 표준 모듈이 '차단 해제' 동작을 가지고 있기 때문에 이 코드가 실행되지 않는다는 것을 알았기 때문에 콘솔에서 답변해야 할 세 가지 질문이 있다고 상상해 보십시오. 각 rl.question은 독립적인 스레드이므로 이 코드는 실행되지 않습니다.
'use strict';
var questionaire=[['First Question: ',''],['Second Question: ',''],['Third Question: ','']];
function askaquestion(question) {
const readline = require('readline');
const rl = readline.createInterface(
{input: process.stdin, output:process.stdout}
);
rl.question(question[0], function(answer) {
console.log(answer);
question[1] = answer;
rl.close();
});
};
var i=0;
for (i=0; i < questionaire.length; i++) {
askaquestion(questionaire[i]);
}
console.log('Results:',questionaire );
실행 중인 출력:
node test.js
Third Question: Results: [ [ 'First Question: ', '' ],
[ 'Second Question: ', '' ],
[ 'Third Question: ', '' ] ] <--- the last question remain unoverwritten and then the final line of the program is shown as the threads were running waiting for answers (see below)
aaa <--- I responded with a single 'a' that was sweeped by 3 running threads
a <--- Response of one thread
a <--- Response of another thread
a <--- Response of another thread (there is no order on threads exit)
제안된 솔루션은 이벤트 이미터를 사용하여 차단 해제 스레드의 끝을 신호하고 루프 로직과 프로그램의 끝을 수신기 기능에 포함합니다.
'use strict';
var questionaire=[['First Question: ',''],['Second Question: ',''],['Third Question: ','']];
// Introduce EventEmitter object
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {};
const myEmitter = new MyEmitter();
myEmitter.on('continue', () => {
console.log('continue...');
i++; if (i< questionaire.length) askaquestion(questionaire[i],myEmitter); // add here relevant loop logic
else console.log('end of loop!\nResults:',questionaire );
});
//
function askaquestion(p_question,p_my_Emitter) { // add a parameter to include my_Emitter
const readline = require('readline');
const rl = readline.createInterface(
{input: process.stdin, output:process.stdout}
);
rl.question(p_question[0], function(answer) {
console.log(answer);
p_question[1] = answer;
rl.close();
myEmitter.emit('continue'); // Emit 'continue' event after the question was responded (detect end of unblocking thread)
});
};
/*var i=0;
for (i=0; i < questionaire.length; i++) {
askaquestion(questionaire[i],myEmitter);
}*/
var i=0;
askaquestion(questionaire[0],myEmitter); // entry point to the blocking loop
// console.log('Results:',questionaire ) <- moved to the truly end of the program
실행 중인 출력:
node test2.js
First Question: 1
1
continue...
Second Question: 2
2
continue...
Third Question: 3
3
continue...
done!
Results: [ [ 'First Question: ', '1' ],
[ 'Second Question: ', '2' ],
[ 'Third Question: ', '3' ] ]
가장 쉬운 방법은 읽기 줄 동기화를 사용하는 것입니다.
입력과 출력을 하나씩 처리합니다.
npm i readline-sync
예:
var firstPrompt = readlineSync.question('Are you sure want to initialize new db? This will drop whole database and create new one, Enter: (yes/no) ');
if (firstPrompt === 'yes') {
console.log('--firstPrompt--', firstPrompt)
startProcess()
} else if (firstPrompt === 'no') {
var secondPrompt = readlineSync.question('Do you want to modify migration?, Enter: (yes/no) ');
console.log('secondPrompt ', secondPrompt)
startAnother()
} else {
console.log('Invalid Input')
process.exit(0)
}
디렉터리를 읽고 콘솔 이름을 새 파일(예: 'name')로 쓰기 위한 작은 스크립트를 만들었습니다.txt') 및 텍스트를 파일로 변환합니다.
const readline = require('readline');
const fs = require('fs');
const pathFile = fs.readdirSync('.');
const file = readline.createInterface({
input: process.stdin,
output: process.stdout
});
file.question('Insert name of your file? ', (f) => {
console.log('File is: ',f.toString().trim());
try{
file.question('Insert text of your file? ', (d) => {
console.log('Text is: ',d.toString().trim());
try {
if(f != ''){
if (fs.existsSync(f)) {
//file exists
console.log('file exist');
return file.close();
}else{
//save file
fs.writeFile(f, d, (err) => {
if (err) throw err;
console.log('The file has been saved!');
file.close();
});
}
}else{
//file empty
console.log('Not file is created!');
console.log(pathFile);
file.close();
}
} catch(err) {
console.error(err);
file.close();
}
});
}catch(err){
console.log(err);
file.close();
}
});
### Building on Rob's answer from 2011
a #CoffeeScript way to do the listener. ###
standin = process.stdin
out = process.stdout
standin.setEncoding('ascii')
# no data values returned inside the function
# are available outside the function.
# So running entire program from listener.
standin.addListener('data', (buffer) ->
arrayIn = buffer.toString().split('\n')
t = lineIn()
console.log("lineIn=" + lineIn() + " line #=" + lineNum
+ " arrayIn=[" + arrayIn + "]")
)
언급URL : https://stackoverflow.com/questions/8128578/reading-value-from-console-interactively
'programing' 카테고리의 다른 글
Mercurial 폴더를 Git 저장소로 변환 (0) | 2023.08.23 |
---|---|
MySql: 열을 표시하지만 필드 이름을 제외한 모든 항목 제외 (0) | 2023.08.23 |
MYSQL 쿼리에서 열의 평균 계산 (0) | 2023.08.18 |
Angular 4에서 매트-페이지네이터를 어떻게 번역합니까? (0) | 2023.08.18 |
MariaDB에서 프롬프트 기록을 제거할 수 있습니까? (0) | 2023.08.18 |