Node.js Why will it only print one at a time - javascript

Im using node.js to list out items from a txt file. I have it to print them out from terminal, however i want it to accept more parameters, as of now it accepts them but only prints one out(the last one) i want it to print each item in the parameter and list them out.
// Make sure we got a filename on the command line.
if (process.argv.length < 3) {
console.log('Usage: node ' + process.argv[1] + ' FILENAME');
process.exit(1);
}
// Read the file and print its contents. And split into an array after each space
var fs = require('fs') , filename = process.argv[2];
var array = fs.readFileSync('dependencies.txt').toString().split('\n');
//console.log(array[0]);
if(process.argv.length >= 3){
for(var j = 3; j < process.argv.length; j++)
var test = process.argv[j];
functionName(test);
}
function functionName(test){
for(var i = 0; i < array.length; i++ ){
var pattern = /([^\s]+)/g;
var line = pattern.exec(array[i]);
if(line && test == line[0]){
console.log(array[i]);
}
}
}
//fs.readFile(filename, 'utf8', function(err, data) {
// if (err) throw err;
// console.log('OK: ' + filename);
// console.log(data)
//});
how it prints out

A for loop can only contain one statement, so if you need more than one, you'll have to wrap it in a block statement.
(Thanks #paulpro)
I would just add a block statement for all for loops, it's more readable that way unless it was short enough to be readable on one line.
for(var j = 3; j < process.argv.length; j++) {
//var test = process.argv[j];
functionName(process.argv[j]);
}
let len = process.argv.length, j = 3;
for (;j<len;j++) functionName(process.argv[j]);

Related

How to shorten these duplicate JavaScript code into a loop?

I had ten rows which each rows contain 4 column, now I want to get the value which I had import using localStorage. I find a way to put all these value independently but the code is all the repeat one. These will cause to redundancy of code. I wonder if there are a way to shorten the code using loop?
Here is my code
var res = {};
$(function(){
$('#subbtn').click(function() {
console.log($('#tab').find('tr'))
$('tr').each(function(){
var tmp = [];
var cl ;
$(this).find('select').each(function(){
cl = $(this).attr('class');
//console.log(cl);
tmp.push($(this).val());
})
res[cl] = tmp
})
console.log(res);
localStorage.setItem("testingvalue",JSON.stringify(res));
document.getElementById("results__display").innerHTML = (localStorage.getItem("testingvalue"));
})
})
$( document ).ready(function(){
var res = {};
try {
console.log('existed');
res = JSON.parse(localStorage.getItem("testingvalue"));
//alert(res.r1[2]);
document.getElementsByClassName("r1")[0].selectedIndex=res.r1[0];
document.getElementsByClassName("r1")[1].selectedIndex=res.r1[1];
document.getElementsByClassName("r1")[2].selectedIndex=res.r1[2];
document.getElementsByClassName("r1")[3].selectedIndex=res.r1[3];
document.getElementsByClassName("r2")[0].selectedIndex=res.r2[0];
document.getElementsByClassName("r2")[1].selectedIndex=res.r2[1];
document.getElementsByClassName("r2")[2].selectedIndex=res.r2[2];
document.getElementsByClassName("r2")[3].selectedIndex=res.r2[3];
document.getElementsByClassName("r3")[0].selectedIndex=res.r3[0];
document.getElementsByClassName("r3")[1].selectedIndex=res.r3[1];
document.getElementsByClassName("r3")[2].selectedIndex=res.r3[2];
document.getElementsByClassName("r3")[3].selectedIndex=res.r3[3];
document.getElementsByClassName("r4")[0].selectedIndex=res.r4[0];
document.getElementsByClassName("r4")[1].selectedIndex=res.r4[1];
document.getElementsByClassName("r4")[2].selectedIndex=res.r4[2];
document.getElementsByClassName("r4")[3].selectedIndex=res.r4[3];
document.getElementsByClassName("r5")[0].selectedIndex=res.r5[0];
document.getElementsByClassName("r5")[1].selectedIndex=res.r5[1];
document.getElementsByClassName("r5")[2].selectedIndex=res.r5[2];
document.getElementsByClassName("r5")[3].selectedIndex=res.r5[3];
document.getElementsByClassName("r6")[0].selectedIndex=res.r6[0];
document.getElementsByClassName("r6")[1].selectedIndex=res.r6[1];
document.getElementsByClassName("r6")[2].selectedIndex=res.r6[2];
document.getElementsByClassName("r6")[3].selectedIndex=res.r6[3];
document.getElementsByClassName("r7")[0].selectedIndex=res.r7[0];
document.getElementsByClassName("r7")[1].selectedIndex=res.r7[1];
document.getElementsByClassName("r7")[2].selectedIndex=res.r7[2];
document.getElementsByClassName("r7")[3].selectedIndex=res.r7[3];
document.getElementsByClassName("r8")[0].selectedIndex=res.r8[0];
document.getElementsByClassName("r8")[1].selectedIndex=res.r8[1];
document.getElementsByClassName("r8")[2].selectedIndex=res.r8[2];
document.getElementsByClassName("r8")[3].selectedIndex=res.r8[3];
document.getElementsByClassName("r9")[0].selectedIndex=res.r9[0];
document.getElementsByClassName("r9")[1].selectedIndex=res.r9[1];
document.getElementsByClassName("r9")[2].selectedIndex=res.r9[2];
document.getElementsByClassName("r9")[3].selectedIndex=res.r9[3];
document.getElementsByClassName("r10")[0].selectedIndex=res.r10[0];
document.getElementsByClassName("r10")[1].selectedIndex=res.r10[1];
document.getElementsByClassName("r10")[2].selectedIndex=res.r10[2];
document.getElementsByClassName("r10")[3].selectedIndex=res.r10[3];
}
catch (error){
console.log(error.message);
}
});
Looking at this repeated line:
document.getElementsByClassName("r1")[0].selectedIndex=res.r1[0];
...a simple first pass improvement would be to just use a nested for loop with variables instead of "r1" and 0:
for (var r = 1; r <= 10; r++) {
for (var i = 0; i < 4; i++) {
document.getElementsByClassName("r" + r)[i].selectedIndex = res["r" + r][i];
}
}
Notice, though, that this means the .getElementsByClassName("r" + r) call happens four time for each value of r, which is not very efficient - it would be better to move that into the outer loop:
var els;
for (var r = 1; r <= 10; r++) {
els = document.getElementsByClassName("r" + r);
for (var i = 0; i < 4; i++) {
els[i].selectedIndex = res["r" + r][i];
}
}
In the second version the inner loop could say i < els.length rather than i < 4, although note that either way you need to be sure you match the number of HTML elements to the number of items in your res object.
You've seem to have the jQuery library loaded. Using jQuery makes this much easier.
Here is an example:
var res = JSON.parse(localStorage.getItem("testingvalue"));
$("tr select").each(function(){
$(this).val(res[$(this).attr("class")][$(this).index()]);
});
Of course, this will only work if the select elements have only one class name and the res object contains values for all the select elements that are inside tr elements. Based on the jQuery code in your question that seems to be the case.
And this is a safer approach
Object.keys(res).forEach(function(key){
res[key].forEach(function(val, index){
$("tr select." + key).eq(index).val(val);
});
});
Code below will work regardless the size of your data in storage:
res = JSON.parse(localStorage.getItem("testingvalue"));
// Let's start with checking 'res' type.
// - if it's an Array, get the the length from .length
// - if it's Object, get the the length from Object.keys().length
var resLength = Array.isArray(res) ? res.length : typeof res === 'object' ? Object.keys(res).length : 0;
// loop throw the rows.
for (var i = 0; i < resLength; i++) {
// Do the same as above: get type of the row and calculate it length for the loop.
var rowLength = Array.isArray(res[i]) ? res.length : typeof res[i] === 'object' ? Object.keys(res[i]).length : 0;
// loop throw the columns on the row.
for (var j = 0; j < rowLength; j++) {
document.getElementsByClassName('r'+i)[j].selectedIndex=res['r'+i][j];
}
}

Javascript Memory Leak in for loop

When I run the following code in node.js I get the following error message:
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory
//Running this code causes program to run out of memory.
for(var i = 0; i < files.length; i++){
readFile(files[i]);
}
//log each line of file to console
function readFile(data){
var lines = fs.readFileSync(data).toString().split('\n');
for(var k = 0; k < lines.length; k++){
console.log(lines[k]);
}
}
But, if I change the readFile function and take the console.log(lines[k]) out of the for loop, the fatal error goes away. Why is that? And how can I fix the original code so it stops running out of memory?
function readFile(data){
var lines = fs.readFileSync(data).toString().split('\n');
var string = ''
for(var k = 0; k < lines.length; k++){
//console.log(lines[k]);
string += lines[k];
}
console.log(string); //log the same string outside the loop and the fatal error goes away
}
do npm install async --save
var async = require('async');
async.eachSeries(files , filesIteration , finishIteration);
function filesIteration(file , callBack){
readFile(file , callBack);
}
function readFile(data , cb){
var lines = fs.readFileSync(data).toString().split('\n');
for(var k = 0; k < lines.length; k++){
console.log(lines[k]);
if(k === lines.length - 1){
cb();
}
}
}
function finishIteration(){
console.log('all files processed');
}

How can I execute a statement AFTER a loop finishes in javascript?

I'm querying a mongo database to retrieve the tiles for the display in rougelike game. This is the function I use:
function get_display(){
var collections = ['austinsroom'];
var db = mongojs(uri, collections);
var temphtml = '';
for(var j = 0; j < 3; j++) {
console.log("y=" + String(j));
db.austinsroom.find({"y": j}, {}).sort({"x": 1}, function(err, records) {
if(err) {
console.log("There was an error executing the database query.");
return;
}
var i = records.length;
while(i--) {
temphtml += records[i].display;
}
temphtml += '<br>';
//console.log(temphtml);
//return temphtml;
//THE ONLY WAY I CAN GET ANYTHING TO PRINT IN THE CONSOLE IS IF I PUT IT INSIDE THE LOOP HERE
});
//console.log(temphtml);
//return temphtml;
//THIS DOES NOTHING
}
//console.log(temphtml);
//return temphtml;
//THIS DOES NOTHING
}
get_display();
If I put the console.log(temphtml) inside the loop, it prints out three times which isn't what I want. I only want the final string (i.e. ...<br>...<br>...<br>. Also I can't ultimately return the temphtml string, which is actually the important thing. Is this some quirk of javascript? Why would it not execute statements after the loop?
Also: is there a better way to retrieve every element of a grid that's stored in a mongo database, in order, so it can be displayed properly? Here's what the mongo documents look like:
{
"_id": {"$oid": "570a8ab0e4b050965a586957"},
"x": 0,
"y": 0,
"display": "."
}
Right now, the game is supposed to display a "." in all empty spaces using the x and y values for the coordinates. The database is indexed by "x" values.
See async.whilst. You want flow control of the for loop, for which this provides a callback to control each loop iteration.
var temphtml = "",
j = 0;
async.whilst(
function() { return j < 3 },
function(callback) {
db.austinsroom.find({"y": j }, {}).sort({"x": 1}, function(err, records)
temphtml += records.map(function(el) {
return el.display;
}).join("") + '<br>';
j++;
callback(err);
});
},
function(err) {
if (err) throw err;
console.log(temphtml);
}
)
Either that or use Promise.all() on collected promises to return "one big result". But you would also need to switch to promised-mongo from mongojs, as the nearest equivalent, since there are more mongodb drivers that actually support promises. That one is just the direct fork from mongojs:
var temphtml = "",
j = 0,
promises = [];
for ( var j=0; j < 3; j++ ) {
promises.push(db.austinsroom.find({"y": j }, {}).sort({"x": 1}).toArray());
promises.push('<br>'); // this will just join in the output
)
Promise.all(promises).then(function(records) {
temphtml += records.map(function(el) {
return el.display;
}).join("");
})
Not exactly the same thing, since it's one list output and not three, but the point is that the Promise objects defer until actually called to resolve, so you can feed the paramters in the loop, but execute later.
I do not use MongoDB but from what I am reading it is asynchronous. So what is happening is your db.austinsroom.find call fires another "thread" and returns to the for loop to continue the next iteration.
One way to do what you want is have a check at the end of your db.austinsroom.find function to see if you're done with the for loop. Something like:
function get_display()
{
var collections = ['austinsroom'];
var db = mongojs(uri, collections);
var temphtml = '';
var doneCounter = 0;
for(var j = 0; j < 3; j++)
{
console.log("y = " + String(j));
db.austinsroom.find({"y": j}, {}).sort({"x": 1}, function(err, records)
{
if(err)
{
console.log("There was an error executing the database query.");
return;
}
var i = records.length;
while(i--)
{
temphtml += records[i].display;
}
temphtml += '<br>';
// we're done with this find so add to the done counter
doneCounter++;
// at the end, check if the for loop is done
if(doneCounter == 3)
{
// done with all three DB calls
console.log(temphtml);
}
});
}
}
This is probably not the best way as I know nothing about MongoDB but it should put you on the right path.

Javascript Learnstreet Email Interpreter Alternative Solution

So I was doing this assignment on Learnstreet and for those of you who want to read a little on the question here's the link:
http://www.learnstreet.com/cg/simple/project/email_interpret#check
Long story short - you're given a email string like "local#domain.com" and you're expected to return a 2 member array that would look like ["local","domain"]. So I wrote this and am wondering how this is not correct.
function extractLocalDomain(str)
{
var text = str.trim(); //eliminates leading and trailing spaces
for(var i = 0; i < text.length; i++) {
if(text[i] == "#") {
var local = text.slice(0, i-1);
var domain = text.slice(i+1)
return [local,domain];
}
i++
}
}
You are incrementing i twice:
function extractLocalDomain(str) {
var text = str.trim();
for (var i = 0; i < text.length; i++) { // <- increment here
if (text[i] == "#") {
var local = text.slice(0, i - 1);
var domain = text.slice(i + 1)
return [local, domain];
}
i++ // <- and here agin, remove this
}
}
Instead of using a loop, you can also just use .indexOf.

For loop in Javascript runs only once

Here is my code. I do not quite understand why the for loop runs only once, both inner and outer. nodeList.length and innerNodeList.length show appropriate values when I generate alert messages. I see that both i and j do not increment beyond 0. Kindly point out anything wrong with the code.
function getCategoryElements() {
var newCategoryDiv = document.getElementById("category");
var nodeList = newCategoryDiv.childNodes;
for (var i = 0; i < nodeList.length; ++i) {
var innerNodeList = nodeList[i].childNodes;
alert("innerNodeList Length" + innerNodeList.length.toString());
for (var j = 0; j < innerNodeList.length; ++j) {
if (innerNodeList[j].nodeName == "SELECT") {
alert("inside select Node value " + innerNodeList[j].nodeValue.toString());
document.getElementById("newCategories").value =
document.getElementById("newCategories").value + '<%=delimiter%>' + innerNodeList[j].nodeValue;
} else if (innerNodeList[j].nodeName == "TEXTAREA") {
document.getElementById("newCategoriesData").value =
document.getElementById("newCategoriesData").value + '<%=delimiter%>' + innerNodeList[j].nodeValue;
}
}
}
}
var newCategoryDiv, nodeList, innerNodeList, innerNode, i, j;
newCategoryDiv = document.getElementById("category");
nodeList = newCategoryDiv.childNodes;
for (i = 0; i < nodeList.length; ++i) {
innerNodeList = nodeList[i].childNodes;
alert("innerNodeList Length" + innerNodeList.length.toString());
for (j = 0; j < innerNodeList.length; ++j) {
innerNode = innerNodeList[j];
if (innerNode.nodeName === "SELECT") {
alert("inside select Node value " + innerNode.nodeValue.toString());
document.getElementById("newCategories").value += '<%=delimiter%>' + innerNode.nodeValue;
} else if (innerNode.nodeName === "TEXTAREA") {
document.getElementById("newCategoriesData").value += '<%=delimiter%>' + innerNode.nodeValue;
}
// Will this work?
alert('Does this alert appear');
}
}
I took the liberty to refactor your code and clean it up a little bit. In case you're not aware, all variables have function scope in Javascript, so no matter where you declare them within a single function, Javascript treats them as if the variable declaration is the first statement.
It appears that your code is syntactically correct, and so I think that the most logical place to look for a problem is that there could be an error occurring after the last alert function call.
In order to check this, try adding another alert function call to the end of the inner loop. If it doesn't run, you'll know this is the case.

Categories

Resources