web-dev-qa-db-ja.com

nodejsで同期readlineを取得する方法、または非同期を使用してそれを「シミュレート」する方法は?

「同期」のreadlineを取得する簡単な方法があるのか​​、少なくともnode.jsで同期I/Oの外観を取得できるのかと思います。

私はこのようなものを使用しますが、それはかなり厄介です

var readline = require('readline');
var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  terminal: false
});

var i = 0;
var s1 = '';
var s2 = '';

rl.on('line', function(line){
    if(i==0) { s1 = line; }
    else if(i==1) { s2 = line; }
    i++;
})

rl.on('close', function() {
    //do something with lines
})'

これの代わりに、私はそれが次のようなものと同じくらい簡単だったらいいと思います

var s1 = getline(); // or "await getline()?"
var s2 = getline(); // or "await getline()?"

役立つ条件:

(a)外部モジュールまたは/ dev/stdioファイルハンドルを使用しないほうがよい。コード送信Webサイトにコードを送信しているが、これらはそこで機能しない

(b)async/awaitまたはジェネレーターを使用できます

(c)ラインベースである必要があります

(d)処理前に標準入力全体をメモリに読み込む必要がない

12
Colin D

私はこれがあなたが望むものだと思います:

const readline = require('readline');

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

const getLine = (function () {
    const getLineGen = (async function* () {
        for await (const line of rl) {
            yield line;
        }
    })();
    return async () => ((await getLineGen.next()).value);
})();

const main = async () => {
    let a = Number(await getLine());
    let b = Number(await getLine());
    console.log(a+b);
    process.exit(0);
};

main();

注:この回答は実験的な機能を使用しており、Node v11.7が必要です。

2
hamid k

将来誰かがここで偶然見つけた場合に備えて

Node11.7のサポートを追加 doc_link async awaitを使用

const readline = require('readline');
//const fileStream = fs.createReadStream('input.txt');

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

for await (const line of rl) {
  console.log(line)
}

非同期関数でラップすることを忘れないでください。そうしないと、reserver_keyword_errorが発生します。

6
Aishwat Singh

readlineモジュールと同様に、同期入力を受け取るreadline-syncと呼ばれる別のモジュールがあります。

例:

const reader = require("readline-sync"); //npm install readline-sync
let username = reader.question("Username: ");
const password = reader.question("Password: ",{ hideEchoBack: true });
if (username == "admin" && password == "foobar") {
    console.log("Welcome!")
}
4
Jaidee

ジェネレータを使用すると、例は次のようになります。

_var readline = require('readline');
var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  terminal: false
});

var i = 0;
var s1 = '';
var s2 = '';

var iter=(function* () {
    s1 = yield;
    i++;
    s2 = yield;
    i++;
    while (true) {
        yield;
        i++;
    }
})(); iter.next();
rl.on('line', line=>iter.next(line))

rl.on('close', function() {
    //do something with lines
})
_

したがって、ここでのyieldは、ブロッキングgetline()であるかのように機能し、通常の順次方式で行を処理できます。


[〜#〜]更新[〜#〜]
また、非同期/待機バージョンは次のようになります。

_var readline = require('readline');
var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  terminal: false
});

var i = 0;
var s1 = '';
var s2 = '';

var continuation;
var getline = (() => {
    var thenable = {
        then: resolve => {
            continuation = resolve;
        }
    };
    return ()=>thenable;
})();
(async function() {
    s1 = await getline();
    i++;
    s2 = await getline();
    i++;
    while (true) {
        await getline();
        i++;
    }
})();
rl.on('line', line=>continuation(line))

rl.on('close', function() {
    //do something with lines
})
_

これらの「同期」バージョンの両方で、iは行を区別するために使用されず、行の総数をカウントするためにのみ役立ちます。

3
Des Nerger

ここに例がありますが、結果を与える前に標準入力全体を読み取る必要がありますが、これは理想的ではありません

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


function lineiterator() {
    var currLine = 0;
    var lines = [];
    return new Promise(function(resolve, reject) {

        rl.on('line', function (line){
            lines.Push(line)
        })
        rl.on('close', function () {
            resolve({
                next: function() {
                    return currLine < lines.length ? lines[currLine++]: null;
                }
            });
        })
    })
}

lineiterator().then(function(x) {
    console.log(x.next())
    console.log(x.next())
})

$ echo test$\ntest | node test.js
test
test
2
Colin D

これを試して。それはまだ同期ライン読み取り機能の完全な複製ではありません-例えばasync関数はまだ後で発生するため、呼び出しコードの一部が順不同で実行される可能性があり、通常のforループ内から呼び出すことはできません-しかし、はるかに読みやすくなっています典型的な.onまたは.questionコードよりも。

// standard 'readline' boilerplate
const readline = require('readline');
const readlineInterface = readline.createInterface({
        input: process.stdin,
        output: process.stdout
});

// new function that promises to ask a question and 
// resolve to its answer
function ask(questionText) {
  return new Promise((resolve, reject) => {
    readlineInterface.question(questionText, (input) => resolve(input) );
  });
}

// launch your program since `await` only works inside `async` functions
start()

// use promise-based `ask` function to ask several questions
// in a row and assign each answer to a variable
async function start() {
  console.log()
  let name = await ask("what is your name? ")
  let quest = await ask("what is your quest? ")
  let color = await ask("what is your favorite color? ")
  console.log("Hello " + name + "! " + 
    "Good luck with " + quest + 
    "and here is a " + color + " flower for you.");
  process.exit() 
}

更新: https://www.npmjs.com/package/readline-promise 実装します(ここにソースコード: https://github.com/bhoriuchi/readline-promise/blob /master/src/index.js#L192 )。他のいくつかの機能も実装していますが、同じことをする他の一部のNPMパッケージとは異なり、機能が多すぎず、あまりにも便利に見えます。残念ながら、 https://github.com/bhoriuchi/readline-promise/issues/5 が原因で機能しませんが、中心的な機能の実装が好きです。

function ask(questionText) {
  return new Promise((resolve, reject) => {
    readlineInterface.question(questionText, resolve);
  });
}
2
AlexChaffee

必要な文字列の数がわからないので、すべてを配列に入れます

より詳細な回答が必要な場合、または私の回答が正確でない場合は、遠慮なくコメントしてください。

var readline = require('readline');
var rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
    terminal: false
});

var i = 0;
var strings = [];

rl.on('line', function(line) {
    // 2 lines below are in case you want to stop the interface after 10 lines
    // if (i == 9)
    //  rl.close()
    strings[i] = line
    i++
}).on('close', function() {
    console.log(strings)
})
// this is in case you want to stop the program when you type ctrl + C
process.on('SIGINT', function() {
    rl.close()
})
0
Amine