Node.js 如何获取同步读线,或;模拟;它是在nodejs中使用异步的吗?
我想知道是否有一种简单的方法来获得“同步”读线,或者至少在node.js中获得同步I/O的外观 我用这样的东西,但很别扭Node.js 如何获取同步读线,或;模拟;它是在nodejs中使用异步的吗?,node.js,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(
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/stdiofilehandle,我正在向一个代码提交网站提交代码,但这些在那里不起作用
(b) 可以使用异步/等待或生成器
(c) 应该是基于行的
(d) 在处理之前不需要将整个stdin读入内存,因为我不知道需要多少字符串,所以我将它们全部放在一个数组中 如果您需要更详细的答案或我的答案不准确,请随时发表评论:
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()
})
这里有一个例子,但它需要在给出结果之前阅读整个标准文本,然而这并不理想
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;
}
});
})
})
}
使用生成器,您的示例如下所示:
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()
一样,您可以按照通常的顺序方式处理行
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
})
在这两个“同步”版本中,
i
不用于区分行,只用于计算行的总数。试试这个。它仍然不是同步行读取函数的完美复制--例如,async
函数仍然会在以后出现,因此您的一些调用代码可能会无序执行,你不能在正常的for
循环中调用它,但它比典型的on
或问题代码更容易阅读
// 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()
}
更新:实现它(这里的源代码:)。它还实现了其他一些功能,但它们似乎也很有用,而且没有太多的工程设计,不像其他一些声称做同样事情的NPM包。不幸的是,由于以下原因,我无法使其工作,但我喜欢它的中心功能的实现:
function ask(questionText) {
return new Promise((resolve, reject) => {
readlineInterface.question(questionText, resolve);
});
}
与readline
模块类似,还有另一个模块名为readline sync
,它接受同步输入
例子:
以防万一将来有人在这里偶然发现
Node11.7使用异步等待添加了对此的支持
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\u关键字\u错误
要读取单个行,可以手动使用异步迭代器
const it = rl[Symbol.asyncIterator]();
const line1 = await it.next();
我想这就是你想要的:
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();
注意:这个答案使用了实验性的特性,需要节点v11.7,你可以把它包装成一个承诺-
const answer = await new Promise(resolve => {
rl.question("What is your name? ", resolve)
})
console.log(answer)
@supersam654 I的可能重复添加了一些额外的条件以消除重复。我的条件是允许使用getline类型函数以干净的“同步”方式使用readline接口读取(单个)行,或者使用“异步/等待”函数进行模拟。这需要将整个stdin读取到内存中,我希望情况不是这样,因为我通过stdin读取大文件,需要流化它是一个流,所以它进入内存的唯一原因是因为我把它放在变量字符串中,但是如果你用它做其他事情,它就不会进入内存。但是我想要perlmy$line=
中的类似内容。或者C++中的GETLIN。这么难吗?我觉得我的请求并不奇怪,我想象它是通过生成器或异步/等待来完成的。真正的问题是你想对所有行做什么?目前,数据行通过stdin管道传输到程序中,数据通常有一些头行,然后是大量数据。标题没有信号,您只需根据问题的需要推断它,数据和标题包含字符串和数字的混合。因此,仅仅控制一个getline函数要比在on('line')回调中调整代码容易得多?例如,在循环之前,我想读一两行,所以我想说like const header=await rl.next(),但这即使在节点11.7@ColinDI中也不起作用。我发现这些答案的语法复杂性是不必要的复杂。我知道这是完全可行的,但我正在寻找一些简单的东西,比如var h1=await rl.next();var h2=等待rl.next();对于await(rl的const行){/*处理文件的其余部分*/}
,但是正如我上面提到的,rl迭代器并没有提供它看起来是这样的!我明白了,vl检查readline和wait的实现
@aishwatching当我使用你的代码时,我在wait的行上发现一个语法错误。意外标记,应为(您能验证它是否仍在工作吗?这看起来不错,例如,在添加这两个数字后,您如何设置一个循环以读取直到输入结束?如果到达EOF,getLine将返回undefined,因此当(1){let x=await getLine();如果(x==undefined)break;/*则使用x*/}这应该是这个问题的正确答案(这是最佳实践)@johannchopin不,这不是我想要的方法。我使用的是通过stdin或大型数据集的管道,而不是问答模块,这就是readline sync的设计目的。还有另一个模块叫做readline async
,以防任何人需要承诺。我喜欢这个解决方案。使用承诺可以利用async/aw的强大功能ait上下文而不需要另一个库。我宁愿将readline接口作为参数传递给ask函数,以便您可以使用不同的接口。
const it = rl[Symbol.asyncIterator]();
const line1 = await it.next();
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();
const answer = await new Promise(resolve => {
rl.question("What is your name? ", resolve)
})
console.log(answer)