如何在nodejs中获取同步readline或使用异步“模拟”它?

Col*_*n D 11 readline node.js

我想知道是否有一种简单的方法来获取“同步” 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
})'
Run Code Online (Sandbox Code Playgroud)

取而代之的是,我希望它像这样简单

var s1 = getline(); // or "await getline()?"
var s2 = getline(); // or "await getline()?"
Run Code Online (Sandbox Code Playgroud)

有用的条件:

(a)建议不要使用外部模块或/ dev / stdio文件句柄,我正在向代码提交网站提交代码,但这些代码在那儿不起作用

(b)可以使用异步/等待或生成器

(c)应基于行

(d)不需要在处理之前将整个标准输入读入内存

ham*_*d k 16

我认为这就是你想要的:

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();
Run Code Online (Sandbox Code Playgroud)

注意:此答案使用实验性功能,需要 Node v11.7


Ais*_*ngh 10

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

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)
}
Run Code Online (Sandbox Code Playgroud)

请记住将其包装在异步函数中,否则您将得到reserver_keyword_error

  • 我可以使用这种方法打电话给一行吗?例如,我在循环之前想,我想读一两行,所以我想说像const header = await rl.next(),但这即使在节点11.7中也不起作用 (2认同)
  • 我发现这些答案的语法复杂性不必要地复杂。我知道这是完全可行的,但我正在寻找一些简单的东西,比如 `var h1 = wait rl.next(); var h2 = 等待 rl.next(); for wait (const line of rl) { /* process rest of file */ }` 但正如我上面提到的 rl 迭代器似乎没有提供这一点 (2认同)

Ale*_*fee 9

尝试这个。它仍然不是同步行读取函数的完美复制——例如,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() 
}
Run Code Online (Sandbox Code Playgroud)

更新: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);
  });
}
Run Code Online (Sandbox Code Playgroud)


Bri*_*rns 9

你可以把它包装在一个承诺中 -

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


Jai*_*dee 6

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!")
}
Run Code Online (Sandbox Code Playgroud)

  • @johannchopin 这不是最佳实践。readline-sync 不是标准的。这是一种依赖.. (5认同)

Des*_*ger 5

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

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
})
Run Code Online (Sandbox Code Playgroud)

所以yield这里就像一个阻塞一样getline(),你可以以通常的顺序方式处理行。


UPD
异步/等待版本可能如下所示:

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
})
Run Code Online (Sandbox Code Playgroud)

在这两个“同步”版本中,i不用于区分行,仅用于计算它们的总数。