सांत्वना से पढ़ना मूल्य, अंतःक्रियात्मक रूप से


155

मैंने सोचा कि कुछ कंसोल एक्सटेंशन के साथ एक साधारण सर्वर 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) { }पाश का उपयोग नहीं कर सकते ? साथ ही अगर सर्वर प्रश्न समय पर आउटपुट प्राप्त करता है, तो यह लाइन को बर्बाद कर देता है।


5
मैं rlआपके द्वारा रीडलाइन मान रहा हूं ?
jpaugh

आप इस उत्तर में उपयोग किए गए जैसे गैर-अवरोधक इंटरफ़ेस का उपयोग कर सकते हैं, फिर आप while(done)लूप कर सकते हैं ।
कीवन

जवाबों:


182

आप "जबकि (किया हुआ)" लूप नहीं कर सकते क्योंकि इनपुट पर अवरोध की आवश्यकता होगी, कुछ नोड। जेएस करना पसंद नहीं करता है।

हर बार कुछ दर्ज किए जाने के बाद कॉलबैक सेट करने के बजाय:

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
धन्यवाद, यह काम करता है, क्या "अंत" श्रोता कुछ समापन कार्यों को कॉल करने और 'अलविदा' कहने की अनुमति देता है?
रिस्टो नोविक

मैंने "अंत" श्रोता को उदाहरण से हटा दिया, मुझे नहीं पता कि यह वास्तव में ईमानदार होने के लिए उपयोगी कहाँ होगा।
लूट

2
आप स्ट्रिंग आउटपुट को d.toString () ट्रिम कर सकते हैं। ट्रिम ()
MKN वेब सॉल्यूशंस

6
इस उत्तर की तारीख 2011 और बहुत कुछ बदल गया है। विशेष रूप से, उत्तर का पहला भाग, आप थोड़ी देर नहीं कर सकते ... अब और नहीं पकड़ता है। हां, आपके पास थोड़ी देर का लूप हो सकता है और फिर भी ब्लॉक नहीं हो सकता है, जो कि एसिंक्स-वेट पैटर्न के लिए धन्यवाद है। अन्य उत्तर दर्शाते हैं कि आजकल इसे पढ़ने वाले किसी भी व्यक्ति के लिए - अन्य उत्तरों के साथ भी सलाह लें।
विकटोर ज़िकला

1
@WiktorZychla पर अनुसरण करने के लिए, फ़ंक्शन प्रक्रिया .openStdin अभी भी काम कर रहा है, 2011 के आसपास हटा दिया गया था, और आपको इसके बारे में कोई दस्तावेज नहीं मिलेगा।
calder.ty

111

मैंने इस उद्देश्य के लिए एक और एपीआई का उपयोग किया है।

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 विवरण पा सकते हैं


11
यह एक बेहतरीन जवाब है। क्या स्पष्ट नहीं हो सकता है (लेकिन यह एक बड़ा प्लस है) कि रीडलाइन बाहरी निर्भरता नहीं है: यह नोड का हिस्सा है।
jlh

51

रीडलाइन एपीआई 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();
});

अधिक जानकारी यहाँ।


5
यह सिर्फ एक मूल उदाहरण है। आप कैसे बातचीत करते हैं? सवाल जवाब? कई विकल्प और पसंद? आरएल को एक बार बंद करने के लिए कैसे, यदि किसी तर्क सहित उपयोगकर्ता के साथ बातचीत करने के लिए ओपन
आरएल के

27

मेरा मानना ​​है कि यह एक आधुनिक 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!

यह ठीक वही उत्तर है जिसकी मुझे तलाश थी। मुझे लगता है कि यह सबसे ऊपर होना चाहिए।
विलियम चाउ

सुंदर। बड़ी स्क्रिप्ट के लिए Async प्रतीक्षा की आवश्यकता है। मुझे ठीक इसी की आवश्यकता थी।
अभय शिरो

25

कृपया रीडलाइन-सिंक का उपयोग करें , इससे आप बिना कॉलबैक हेल्स के सिंक्रोनस कंसोल के साथ काम कर सकते हैं। पासवर्ड के साथ भी काम करता है:

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


5
इसके लिए अतिरिक्त निर्भरता की आवश्यकता होती है इसलिए मैं अन्य समाधानों को प्राथमिकता दूंगा।
रिस्तो नोविक

एसओ पर नहीं चलता है "
अनक्रीफाइड रेफरेंसएयर

12

@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')जब स्टड रीडर हमारे इनपुट को पढ़ता है तो हमें सूचित करेगा। चूँकि हम पिछले डेटा को स्टोर कर रहे हैं, अब हम इसे एक साथ पढ़ सकते हैं और प्रोसेस कर सकते हैं।


3
जब मैं ऊपर दिए गए कोड का उपयोग कर रहा हूं और कुछ इनपुट डालें और फिर "एंटर" करें तो कंसोल मुझे अधिक इनपुट के लिए पूछ रहा है। हम इसे कैसे समाप्त कर सकते हैं?
मटन तुबुल

5

मैं इन्क्वायरर का उपयोग करने की सलाह देता हूं , क्योंकि यह सामान्य इंटरैक्टिव कमांड लाइन उपयोगकर्ता इंटरफेस का संग्रह प्रदान करता है।

const inquirer = require('inquirer');

const questions = [{
  type: 'input',
  name: 'name',
  message: "What's your name?",
}];

const answers = await inquirer.prompt(questions);
console.log(answers);

5

यहाँ एक उदाहरण है:

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

अच्छा जवाब भाई !! बस सरल और स्पष्ट।
MD.JULHAS HOSSAIN

3

यह अधूरा है। का एक आसान संस्करण:

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

2

एक सामान्य उपयोग का मामला संभवतः ऐप के लिए एक सामान्य संकेत प्रदर्शित करने और इसे स्विच स्टेटमेंट में संभालने के लिए होगा।

आप कॉलबैक में खुद को कॉल करने वाले सहायक फ़ंक्शन का उपयोग करके कुछ समय लूप के बराबर व्यवहार प्राप्त कर सकते हैं:

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> 'यदि आपका ऐप पहले से ही इस लूप के बाहर स्क्रीन पर कुछ प्रिंट करता है तो आप इसके बजाय एक खाली स्ट्रिंग पास कर सकते हैं ।


2

इसके लिए मेरा दृष्टिकोण async जनरेटर का उपयोग करना होगा ।

यह मानते हुए कि आपके पास प्रश्नों की एक सरणी है:

 const questions = [
        "How are you today ?",
        "What are you working on ?",
        "What do you think of async generators ?",
    ]

awaitकीवर्ड का उपयोग करने के लिए , आपको अपने प्रोग्राम को एक async IIFE में लपेटना होगा।

(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' ] ]
   */

2

मुझे नोड में एक "टिक-टैक-टो" गेम लिखना था, जो कमांड लाइन से इनपुट लेता था, और इस कोड के मूल async / प्रतीक्षा ब्लॉक को लिखा था जिसने चाल चली थी।

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

1

रीडलाइन अनब्लॉक किए गए व्यवहार को अवरुद्ध करना

कल्पना करें कि आपके पास कंसोल से उत्तर देने के लिए तीन प्रश्न हैं, क्योंकि अब आप जानते हैं कि यह कोड नहीं चलेगा क्योंकि रीडलाइन मानक मॉड्यूल ने 'अनब्लॉक' व्यवहार को कहा है कि प्रत्येक 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' ] ]

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

0

सबसे आसान तरीका रीडलाइन-सिंक का उपयोग करना है

यह एक इनपुट और एक पुट द्वारा प्रोसेस करता है।

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

आपको वास्तव में अपना requireबयान शामिल करना चाहिए । इसे छोड़ने का कोई कारण नहीं है।
सॉलिडस्टेटजेक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.