I'm new to nodejs I was trying the append function.
When I run below code that simply takes User input after prompting him, about fav singer and puts in a file with singer name. And appending fav songs, It seems if user entered exit it should be append it to the file but, its not???
Meanwhile if its change to appendFileSync (Synchronous version of the fn) exit is added??
Code:
var readline = require ('readline');
var fs = require('fs');
var rl = readline.createInterface(process.stdin, process.stdout);
var singer = {
name:'',
songs: []
};
rl.question("What is your fav singer? ", function(answer) {
singer.name = answer;
//creating a file for this singer
fs.writeFileSync(singer.name+".md", `${singer.name}\n====================\n\n`);
rl.setPrompt(`What's your fav songs for ${singer.name} ?`);
rl.prompt();
rl.on('line', function(song) {
singer.songs.push(song.trim());
fs.appendFile(singer.name+".md", `* ${song.trim()} \n`);
//***** WHY IF ITS EXIT ITS NEVER APPEND IT TO THE FILE
console.log(`* ${song.trim()} \n`);
if (song.toLowerCase().trim() === 'exit') {
fs.appendFile(singer.name+".md", "Bye");
//***** WHY ITS NEVER APPEND IT TO THE FILE
rl.close();
} else {
rl.setPrompt(`what else would ${singer.name} say? ('exit'to leave)`);
rl.prompt();
}
});
});
rl.on ('close', function() {
console.log ("%s is a real person that says %j", singer.name, singer.songs);
process.exit();
});
Because fs.appendFile is asynchronous. When you call it, io operations are queued only. Unfortunately, your script exits before the real io-operations happen.
So. you have to use either fs.appendFileSync or fs.appendFile with callback (the 3rd argument) and when the callback is called, do all further activities.
Related
I have two codes one for reading shared file using smb2:
// load the library
var SMB2 = require('smb2');
// create an SMB2 instance
var smb2Client = new SMB2({
share:'\\\\192.168.0.111\\folder'
, domain:'WORKGROUP'
, username:'username'
, password:'password'
});
// read the file
smb2Client.readFile('path\\to\\the\\file.txt', "utf-8", function(error, data){
if(error) throw error;
console.log(data);
});
And the other one for reading the last 20 lines of a local file using read-last-line:
// load the library
const readLastLine = require('read-last-line');
// read the file
readLastLine.read('path\\to\\the\\file.txt', 20).then(function (lines) {
console.log(lines)
}).catch(function (err) {
console.log(err.message);
});
I didn't know how to combine the two of them.
Do you have any suggestions.
Thanks.
If smb2 and read-last-line both supported streams, it would be easy. According to their documentation at least, neither does, but pv-node-smb2 has a method createReadStream.
Here is a stream transformer that processes its input line by line, but keeps only the most recent n lines and outputs them at the end. This avoids keeping huge files entirely in memory:
class Tail extends stream.Transform {
constructor(n) {
super();
this.input = new stream.PassThrough();
this.tail = [];
readline.createInterface({input: this.input, crlfDelay: Infinity})
.on("line", function(line) {
if (this.tail.length === n) this.tail.shift();
this.tail.push(line);
}.bind(this));
}
_transform(chunk, encoding, callback) {
this.input.write(chunk);
callback();
}
_flush(callback) {
callback(null, this.tail.join("\n"));
}
}
(Likely, there is already an NPM package for that.)
Now you can pipe the SMB2 read stream through that transformer:
new require("pv-node-smb2").PvNodeSmb2(...).createReadStream(...)
.pipe(new Tail(20))
.pipe(process.stdout);
I couldn't install pv-node-smb2 package, it gave me too much errors so I tried a Powershell command that works like the tail command in Linux
Get-Content \\192.168.0.111\path\to\the\file.txt -Tail 20
Which returns the last 20 lines of the file and then run that script in NodeJs
let last20lines = "";
let spawn = require("child_process").spawn,child;
child = spawn("powershell.exe",["c:\\wamp64\\www\\powershell_script.ps1"]);
child.stdout.on("data",function(data){
last20lines += data
});
child.stdin.end();
I am struggling through learning JQuery/Javascript and have a web application using the chrome "experimental" web serial API. When I enter a command and get a response back, this string is broken into 2 pieces in a random place, usually in the first third:
<p0><iDCC-EX V-0.2.1 / MEGA / STANDARD_MOTOR_SHIELD G-9db6d36>
All the other return messages are shorter and also wrapped in "<" and ">" brackets.
In the code below. The log window only ever shows the second chunk, even in the "ChunkTransformer() routine that simultaneously displays it properly in the devtools console log.
How can I get all my return messages to appear as one string? It is ok if the chunks are split as separate return values by the brackets as long as they display in the log. I think the <p0> is not displaying because the log window thinks it is a special character. It would not even display here until I wrapped in in a code tag. So I think I have at least two issues.
async function connectServer() {
try{
port = await navigator.serial.requestPort(); // prompt user to select device connected to a com port
await port.open({ baudRate: 115200 }); // open the port at the proper supported baud rate
// create a text encoder output stream and pipe the stream to port.writeable
const encoder = new TextEncoderStream();
outputDone = encoder.readable.pipeTo(port.writable);
outputStream = encoder.writable;
// send a CTRL-C and turn off the echo
writeToStream('\x03', 'echo(false);');
let decoder = new TextDecoderStream();
inputDone = port.readable.pipeTo(decoder.writable);
inputStream = decoder.readable
// test why only getting the second chunk in the log
.pipeThrough(new TransformStream(new ChunkTransformer()));
// get a reader and start the non-blocking asynchronous read loop to read data from the stream.
reader = inputStream.getReader();
readLoop();
return true;
} catch (err) {
console.log("User didn't select a port to connect to")
return false;
}
}
async function readLoop() {
while (true) {
const { value, done } = await reader.read();
if (value) {
displayLog(value);
}
if (done) {
console.log('[readLoop] DONE'+done.toString());
displayLog('[readLoop] DONE'+done.toString());
reader.releaseLock();
break;
}
}
}
class ChunkTransformer {
transform(chunk, controller) {
displayLog(chunk.toString()); // only shows last chunk!
console.log('dumping the raw chunk', chunk); // shows all chunks
controller.enqueue(chunk);
}
}
function displayLog(data){
$("#log-box").append("<br>"+data+"<br>");
$("#log-box").animate({scrollTop: $("#log-box").prop("scrollHeight"), duration: 1}, "fast");
}
First Step:
Modify the displayLog() function in one of the following ways
With Animate:
function displayLog(data){
$("#log-box").append("<br>"+data+"<br>");
$("#log-box").animate({scrollTop: $("#log-box").prop("scrollHeight")}, "fast");
}
Without Animate:
function displayLog(data){
$("#log-box").append("<br>"+data+"<br>");
$("#log-box").scrollTop( $("#log-box").prop("scrollHeight"));
}
OR Just for your understanding:
function displayLog(data){
$("#log-box").append("<br>"+data+"<br>");
scrollHeight = $("#log-box").prop("scrollHeight");
$("#log-box").scrollTop(scrollHeight);
}
This question already has answers here:
Get user input through Node.js console
(6 answers)
Closed last month.
I'm working on a JS project running with node.js and I can't figure out how to get the prompt to work correctly for user input. I installed it from npm, followed the steps and I can get the program to prompt for user input but I can't store the result in a variable.
What I want is to prompt the user for his next move (up,down,left or right) every turn and use the result. I tried making a global move variable and affecting it in the prompt section, but it doesn't seem to work.
var Moving = function(maxMoves){
for(var n=maxMoves; n>0;){
var move;
var l;
//This would prompt for a direction (up,down,left,right)
move = prompt();
//And this would prompt for the number of tiles to advance;
l = prompt();
Direction(move,l);
n-=l;
}
};
Using require('prompt') or require('readline') are both good, easy ways to do this, but I wanted to find THE EASIEST WAY, and I didn't care about whether it is synchronous or asynchronous. Finding it took me longer than it should have, so maybe I can save people some time if they read this before digging any further.
Here you go:
# npm install readline-sync
var readline = require('readline-sync');
var name = readline.question("What is your name?");
console.log("Hi " + name + ", nice to meet you.");
Disclaimer: I am just spreading the word, here are my sources:
https://teamtreehouse.com/community/how-to-get-input-in-the-console-in-nodejs
How to take in text input from a keyboard and store it into a variable?
When you say "installed it from npm" I'm assuming you're referring to the prompt module from flatiron.
From their docs, as with most Node things, it looks like it exposes an asynchronous function, so you'll handle input inside the prompt callback:
var prompt = require('prompt');
//
// Start the prompt
//
prompt.start();
//
// Get two properties from the user: username and email
//
prompt.get(['username', 'email'], function (err, result) {
//
// Log the results.
//
console.log('Command-line input received:');
console.log(' username: ' + result.username);
console.log(' email: ' + result.email);
});
Storing it in a variable would be no different than accessing it from the result object above, but realize that since it's async it'll only be reliable available inside that callback.
you can use two packages readline and prompt
Here's a simple example with readline package https://nodejs.org/en/knowledge/command-line/how-to-prompt-for-command-line-input/
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('What is your name ? ', function (name) {
rl.question('Where do you live ? ', function (country) {
console.log(`${name}, is a citizen of ${country}`);
rl.close();
});
});
rl.on('close', function () {
console.log('\nBYE BYE !!!');
process.exit(0);
});
Here is an another example with prompt package. https://www.npmjs.com/package/prompt
const prompt = require('prompt');
prompt.start();
prompt.get(['username','email'], function (err, result) {
console.log('Command-line input received:');
console.log(' username: ' + result.username);
console.log(' email: ' + result.email);
});
inquirer module has a prompt function.
Use
const { prompt } = require('inquirer');
prompt([array] | object | string ')
Objective
Figure what is wrong with my code, or if underscore.js throttle works as it should.
Background
I have a huge list of postal codes in a file, and I am reading those codes and pasting them on console.
I am trying to use Underscore.js throttle() function, however my code stops after two runs (even though I have dozens), and the rest of the values are never printed.
Code
My code is in a very simple NodeJS project. I created a MCVE of the situation I am facing:
"use strict";
//requiremetns
let fs = require('fs');
let readLine = require('readline');
let _ = require('underscore');
//constants
const INPUT_FILE = 'dataset.txt';
const RADIX_CONVERSATION = 10;
const THROTTLE_DELAY = 500;
let init = function() {
let lineReader = readLine.createInterface({
input: fs.createReadStream(INPUT_FILE),
output: process.stdout,
terminal: false
});
let throttledRequestFn = _.throttle(requestFn, THROTTLE_DELAY);
lineReader.on('line', function(line) {
line = line.trim();
if (_.isNaN(parseInt(line, RADIX_CONVERSATION))) {
//Do some stuff
}
else {
throttledRequestFn('mahCountry', line);
}
});
};
let requestFn = function(country, postalCode){
console.log('request for ' + country + ' and postal ' + postalCode + ' done');
return false;
};
init();
Here I first start by reading the file, one line at a time. Then if the line I am reading is a number, I print something, otherwise nothing.
Following is a test file:
Vietnam
000000
100000
160000
170000
180000
200000
220000
230000
240000
250000
260000
270000
280000
290000
300000
310000
320000
330000
350000
360000
380000
390000
400000
410000
420000
430000
440000
460000
480000
510000
520000
530000
550000
560000
570000
580000
590000
600000
620000
630000
640000
650000
660000
670000
700000
790000
800000
810000
820000
830000
840000
850000
860000
870000
880000
890000
900000
910000
920000
930000
940000
950000
960000
970000
Question
The way I see it, my code should make 2 requests per second, with a 500 ms of delay between each one. It should print all the codes in the test file.
However, I never seen anything past the second value! Why is this happening?
The throttle function is working as intended. From the documentation:
Useful for rate-limiting events that occur faster than you can keep up with.
This means that your wrapped function will probably be called less often than you want.
What you actually want is probably some kind of queue. Underscore doesn't provide one, but the async library does: http://caolan.github.io/async/docs.html#.queue
let fs = require('fs');
let readLine = require('readline');
let _ = require('async');
// import the async library
let async = require('async');
const INPUT_FILE = 'dataset.txt';
const RADIX_CONVERSATION = 10;
// create the queue
var q = async.queue(function(task, callback) {
// make sure the queue task calls the callback only after the THROTTLE_DELAY
setTimeout(function () {
requestFn(task.country, task.postalCode);
callback();
}, THROTTLE_DELAY);
}, 1)
q.drain = function () {
console.log('all items have been processed');
};
let init = function () {
let lineReader = readLine.createInterface({
input: fs.createReadStream(INPUT_FILE),
output: process.stdout,
terminal: false
});
lineReader.on('line', function(line) {
line = line.trim();
if (_.isNaN(parseInt(line, RADIX_CONVERSATION))) {
// Do some stuff
}
else {
// Add the line to the Queue, to be executed later
q.push({country: 'mahCountry', postalCode: line});
}
});
};
let requestFn = function(country, postalCode){
console.log('request for ' + country + ' and postal ' + postalCode + ' done');
return false;
};
init();
Notice the use of setTimeout in the function that handles the elements in the queue. That way, you'll still only make one request every 500ms, but will be guaranteed to make all of them.
I wan't to log into a file continuously, but after every 1000 lines I want to change to a new file. Now my method works like this:
var fs = require('fs');
...
var outputStream = fs.createWriteStream(fileName + '.csv');
outputStream.write(content, 'utf8', callback);
...
if (lineCounter === 1000) {
outputStream.end(function(err) {
outputStream = fs.createWriteStream(fileName2 + '.csv');
outputStream.write(content, 'utf8', callback);
});
}
In the end the files doesn't contains the last few lines. I'm open for any solution, I just need stream write into several files.
Thanks in advance!
At first I tried using the streams of Highland.js but I couldn't pause them for some reason. The script I am posting is tested and it is working. I share the original source at the end. So, I haven't actually start reading second file, but I believe it is easy now, as you have a point to proceed further after the script has reached the defined limit of lines.
var stream = require('stream'),
fs = require('fs'),
readStream = fs.createReadStream('./stream.txt', {highWaterMark: 15}),
limitStream = new stream.Transform(),
limit = 0
limitStream._transform = function(chunk, encoding, cb) {
if (++limit <= 5) {
console.log('before', limit)
return cb(null, chunk + '\n')
}
console.log('after',limit)
this.end()
cb()
}
limitStream.on('unpipe', function() { console.log('unpipe emitted from limitStream') })
limitStream.on('end', function() { console.log('end emitted from limitStream') })
readStream.pipe(limitStream).pipe(process.stdout)
Source: https://groups.google.com/forum/#!topic/nodejs/eGukJUQrOBY
After posting the answer, I found library, that can also work, but I admit that I haven't tested it. I just share it as a reference point: https://github.com/isaacs/truncating-stream