如何获得同步readline,或"模拟"它在nodejs中使用async?

时间:2017-04-26 15:10:50

标签: node.js 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文件句柄,我会将代码提交给代码提交网站,而这些代码在那里不起作用

(b)可以使用async / await或generator

(c)应该是基于行的

(d)在处理之前不应要求将整个stdin读入内存

8 个答案:

答案 0 :(得分:3)

以防万一将来有人偶然发现这里

Node11.7 使用异步等待功能为此doc_link添加了支持

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

答案 1 :(得分:2)

这是一个例子,但它需要在给出结果之前读取整个标准输入,但这并不理想

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 :(得分:2)

使用生成器,您的示例如下所示:

SliderVariable

所以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,你可以按照通常的顺序方式处理行。

<强> UPD
async / await版本可能如下所示:

getline()

在这两个&#34;同步&#34;版本,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 }) 不用于区分行,仅用于计算它们的总数。

答案 3 :(得分:2)

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 :(得分:2)

我想这就是你想要的:

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

答案 5 :(得分:2)

您可以将其包装成一个承诺-

const answer = await new Promise(resolve => {
  rl.question("What is your name? ", answer => resolve(answer))
})
console.log(answer)

答案 6 :(得分:1)

尝试一下。它仍然不是同步线路读取功能的完美复制-例如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);
  });
}

答案 7 :(得分:0)

由于我不知道你需要多少个字符串,我把它们全部放在一个数组中

如果您需要更详细的答案或我的答案不准确,请不要犹豫评论:

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