Reputation: 177
Is there a simple way in node.js
to do something like this, i.e. a function, e.g., readline
reading exact one line from stdin
and returning a string?
let a = parseInt(readline(stdin));
let b = parseFloat(readline(stdin));
I don't wish to read a whole block of lines and parse it line by line, like using process.stdin.on("data")
or rl.on("line")
.
In the answer provided in http://stackoverflow.com/questions/20086849/how-to-read-from-stdin-line-by-line-in-node, every line is processed by the same function block, and I still can not assign each line to a variable on reading a line.
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
});
rl.on('line', function(line){
console.log(line);
})
Upvotes: 1
Views: 2136
Reputation: 4336
It's pretty evident that reading a line from a stream is going to be an async operation anyway. (as you don't know when the line actually appears in the stream). So you should deal either with callbacks/promises or with generators. And when the read happens you get the line (in a callback, as a value returned in .then or simply by assign it to a variable as you want if you use generators).
So if it's an option for you to use ES6 and comething like 'co' to run the generator here is what you can try.
const co = require('co');
//allows to wait until EventEmitter such as a steam emits a particular event
const eventToPromise = require('event-to-promise');
//allows to actually read line by line
const byline = require('byline');
const Promise = require('bluebird');
class LineReader {
constructor (readableStream) {
let self = this;
//wrap to receive lines on .read()
this.lineStream = byline(readableStream);
this.lineStream.on('end', () => {
self.isEnded = true;
});
}
* getLine () {
let self = this;
if (self.isEnded) {
return;
}
//If we recieve null we have to wait until next 'readable' event
let line = self.lineStream.read();
if (line) {
return line;
}
yield eventToPromise(this.lineStream, 'readable');
//'readable' fired - proceed reading
return self.lineStream.read();
}
}
I used this to run it for test purposes.
co(function *() {
let reader = new LineReader(process.stdin);
for (let i = 0; i < 100; i++) {
//You might need to call .toString as it's a buffer.
let line = yield reader.getLine();
if (!line) {break;}
console.log(`Received the line from stdin: ${line}`);
}
});
Definitely it's going to work out of the box if you're using koa.js (generator based Express-like framework)
If you do not want ES6 you can do the same on bare Promises. It is going to be something like this. http://jsbin.com/qodedosige/1/edit?js
Upvotes: 2