What is experimental in this Node snippet that reads a file? - javascript

I was running code from here:
https://nodejs.org/dist/latest-v10.x/docs/api/readline.html#readline_example_read_file_stream_line_by_line
const fs = require('fs');
const readline = require('readline');
async function processLineByLine() {
const fileStream = fs.createReadStream('input.txt');
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
// Note: we use the crlfDelay option to recognize all instances of CR LF
// ('\r\n') in input.txt as a single line break.
for await (const line of rl) {
// Each line in input.txt will be successively available here as `line`.
console.log(`Line from file: ${line}`);
}
}
processLineByLine();
and got this warning:
(node:13735) ExperimentalWarning: readline Interface [Symbol.asyncIterator] is an experimental feature. This feature could change at any time
(node:13735) ExperimentalWarning: Readable[Symbol.asyncIterator] is an experimental feature. This feature could change at any time
What is experimental exactly? There is no line number.

It says:
readline Interface [Symbol.asyncIterator]
So look for an interface:
const rl = readline.createInterface
that you are iterating over:
const line of rl

Related

Not reading text in a right way node js

I am working on a sales tax problem with node js and I am trying to read text from a file input.txt then calculate the taxes and prices as a final output.
I used the function below to read the file input.txt line by line and it's working
var fs = require('fs'),
readline = require('readline');
var rl = readline.createInterface({
input : fs.createReadStream('input.txt'),
output: process.stdout,
terminal: false
})
rl.on('line',function(line){
console.log(line)
})
But the problem is when I tried use the function scanProduct() on that text it didn't work.
This is the whole code
var Cart = require('./src/Cart');
var cart1 = new Cart();
var cart2 = new Cart();
var cart3 = new Cart();
cart1.scanProduct('1 book at 12.49');
cart1.scanProduct('1 music CD at 14.99');
cart1.scanProduct('1 chocolate bar at 0.85');
cart2.scanProduct('1 imported box of chocolates at 10.00');
cart2.scanProduct('1 imported bottle of perfume at 47.50');
// cart3.scanProduct('1 imported bottle of perfume at 27.99');
// cart3.scanProduct('1 bottle of perfume at 18.99');
// cart3.scanProduct('1 packet of headache pills at 9.75');
// cart3.scanProduct('1 box of imported chocolates at 11.25');
var fs = require('fs'),
readline = require('readline');
var rl = readline.createInterface({
input : fs.createReadStream('input.txt'),
output: process.stdout,
terminal: false
})
rl.on('line',function(line){
//console.log(line)
cart3.scanProduct(line)
})
console.log(cart1.bill());
console.log("\n");
console.log(cart2.bill());
console.log("\n");
console.log(cart3.bill());
scanProduct() and bill() are fuction used to calculate taxes and give the final output and it's working in cart1 and car2 that way. When I tried to get text from the file it didn't work.
It fails because reading of a file is an asynchronous operation and cart3.bill()
function is called before cart3.scanProduct(line) function.
You should listen to an 'end' event of a readable stream then call the cart3.bill() function.
Like this:
rl.on('end',function(){
console.log(cart3.bill());
})

NodeJS autocomplete shadow. How to implement it?

How is autocomplete shadow in nodejs implemented as a console application?
By "autocomplete shadow" I mean ... as I type in the node REPL 'func' without hitting tab I get a shadow of the keyword 'function':
How can I do this in my own console app:
// Simple REPL with tab completion ... how to make it into a REPL with shadow completion?
const readline = require('readline')
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
completer: (line) => { // This will only give me tab completion
const completions = ['function', 'let', 'const']
const hits = completions.filter(completion => completion.startsWith(line))
return [hits.length ? hits : completions, line]
}
})
rl.prompt()
rl.on('line', input => {
console.log(input)
rl.prompt()
})

Querying Primary Device Attributes

I'm trying to query for sixel support in Node.js using the Primary Device Attributes ANSI escape code but I can't find a way to catch the terminal response.
In a Linux environment, it's as simple as
echo -e '\e[0c'
However, in Node.js executing a command and capturing its stdin reply appears harder than it sounds.
Since not all OSes and environments support the -e option, I need to create a Node.js implementation that does that in a different way.
I started by trying to use readline:
const readline = require("readline")
const ESC = '\u001B[';
const askText = prompt => new Promise((resolve) => {
const rl = readline.createInterface(process.stdin, process.stdout)
rl.question(prompt, (answer) => {
resolve(answer)
rl.close()
})
})
askText(ESC + "0c").then(console.log)
but this just showed a prompt and waited for the user to press enter.
I also tried streaming it and logging it to no avail
const readline = require("readline")
const toReadableStream = require("to-readable-stream")
const wstream = require("fs").createWriteStream("a.txt")
const rl = readline.createInterface({
input: toReadableStream(code), output: wstream
})
rl.on("line", (line) => {
console.log(`Received: ${JSON.stringify(line)}`);
})
I also investigated using child_process.exec but it doesn't support a stdin output as far as I can tell.
How should I actually do this?
Here's a simple solution (suggested by #jerch):
const ESC = "\u001B["
stdin.setEncoding("utf8")
stdin.setRawMode(true)
stdin.once("data", data => {
// Handle resulting data...
stdin.setRawMode(false)
stdin.destroy()
})
stdout.write(ESC + '0c')

Show file lines with delay in Node.js

I am trying to make a program in node.js that reads a text file line by line and shows each of them with a delay of 2 seconds. The code I am testing is the following.
var fs = require('fs'),
readline = require('readline');
var FileSystem_Lectura=function()
{
this._rd=null;
}
FileSystem_Lectura.prototype.abrirArchivoCSV=function(nombreArchivo)
{
this._rd = readline.createInterface
({
input: fs.createReadStream(nombreArchivo),
output: process.stdout,
terminal: false
});
}
FileSystem_Lectura.prototype.leerArchivoCSV=function()
{
self=this;
this._rd.on('line',self.mostraLineasDelay);
}
FileSystem_Lectura.prototype.mostraLineasDelay=function(linea)
{
setTimeout(self.mostraLinea,20000,linea);
}
FileSystem_Lectura.prototype.mostraLinea=function(linea)
{
console.log("Linea:"+ linea);
}
var FS =new FileSystem_Lectura();
FS.abrirArchivoCSV(process.argv[2]);
FS.leerArchivoCSV();
The problem is that settimeout shows me all the lines together, it does not apply the delay. Except for the first line. So, how can I make it work properly?
From already thank you very much
Use pause/resume on your stream :
var fs = require('fs'),
readline = require('readline');
var FileSystem_Lectura=function()
{
this._rd=null;
}
FileSystem_Lectura.prototype.abrirArchivoCSV=function(nombreArchivo)
{
this._rd = readline.createInterface
({
input: fs.createReadStream(nombreArchivo),
output: process.stdout,
terminal: false
});
}
FileSystem_Lectura.prototype.leerArchivoCSV=function()
{
self=this;
this._rd.on('line',self.mostraLineasDelay);
}
FileSystem_Lectura.prototype.mostraLineasDelay=function(linea)
{
this._rd.pause();
setTimeout(self.mostraLinea,2000,linea);
}
FileSystem_Lectura.prototype.mostraLinea=function(linea)
{
console.log("Linea:"+ linea);
this._rd.resume();
}
Also, 2 seconds is 2000ms, not 20000.
This sort of thing is way easier these days:
import {createInterface} from 'readline';
import {createReadStream} from 'fs';
import {pipe, delay} from 'iter-ops';
const file = createInterface(createReadStream('./my-file.txt'));
const i = pipe(file, delay(2000)); //=> AsyncIterable<string>
(async function () {
for await(const line of i) {
console.log(line); // prints line-by-line, with 2s delays
}
})();
Libraries readline and fs are now standard. And iter-ops is an extra module.

Node.js start reading a file on a specific line

On Node.js we can read a file line by line using the readline module:
var fs = require('fs');
var readline = require('readline');
var rl = readline.createInterface({
input: fs.createReadStream('filepath');
});
rl.on('line', function(line) {
console.log(`Line read: ${line}`);
});
But what if we want to start reading on a specific line number? I know that when we use the createReadStream we can pass in a start parameter. This is explained in the docs:
options can include start and end values to read a range of bytes from the file instead of the entire file.
But here start is one offset in bytes, so it seems complicated to use this to set the starting line.
How can we adapt this approach to start reading a file on a specific line?
You have to read the file from the beginning and count lines and start processing the lines only after you get to a certain line. There is no way to have the file system tell you where a specific line starts.
var fs = require('fs');
var readline = require('readline');
var cntr = 0;
var rl = readline.createInterface({
input: fs.createReadStream('filepath');
});
rl.on('line', function(line) {
if (cntr++ >= 100) {
// only output lines starting with the 100th line
console.log(`Line read: ${line}`);
}
});

Categories