Basically what I am trying to do here is , do nmap scan on 7 machines using nmap/nodejs and then when the response comeback, I am writing it to the client page.
When I run this it works fine.Its using closure, to wrap the variable count, so every callback gets count = 0.
Now what I don't understand is, why is the value of count increasing from 1 to 7 as per the console.log. As per my understanding, every method gets a count.
Can someone please explain why this is
Output from nodejs ::
server is listening
8.8.8.1
8.8.8.2
8.8.8.3
8.8.8.4
8.8.8.5
8.8.8.6
8.8.8.8
count = 1
count = 2
count = 3
count = 4
count = 5
count = 6
count = 7
ending the response
Code ::
var http = require('http');
var cb = function(httpRequest, httpResponse){
var count = 0;
var ips = [];
ips.push('8.8.8.1');
ips.push('8.8.8.2');
ips.push('8.8.8.3');
ips.push('8.8.8.4');
ips.push('8.8.8.5');
ips.push('8.8.8.6');
ips.push('8.8.8.8');
var exec = require('child_process').exec;
for(var i =0; i< ips.length ; i++)
{
exec('nmap.exe -v ' + ips[i], function(error, stdout, stderr) {
if(error)
{
httpResponse.write(stderr);
httpResponse.write("</br>")
httpResponse.write("*************************");
}
else
{
httpResponse.write(stdout);
httpResponse.write("</br>")
httpResponse.write("*************************");
}
count = count + 1;
console.log('count = ' + count);
if (count === 7)
{
console.log('ending the response');
httpResponse.end();
}
});
console.log(ips[i]);
}
}
var server = http.createServer(cb);
server.listen(8080, function(){
console.log('server is listening');
});
-Thanks
Because count is declared in the global space in line 3 of your code, each loop is increasing the outer count by one. This will not cause your count to reset. If you want to instantiate a new count variable, you need to declare var count within your loop instead.
count is increasing from 1 to 7 because you're increasing it by 1 on every iteration of the loop which loops over the array of ips which contain 7 elements. Every new request gets the count reset to 0. Every request you are iterating through all 7 elements.
It looks like you are wanting to use closures on the count variable. However, you did not implement closures on the count variable. In order to pass a copy of count to each asynchronous function you should wrap the corresponding blocks of code in a function call that takes count as an argument. For Example:
var exec = require('child_process').exec;
for(var i =0; i< ips.length ; i++)
{
(function(count) { //Start of closure function storing a local copy of count
exec('nmap -v ' + ips[i], function(error, stdout, stderr) {
if(error)
{
httpResponse.write(stderr);
httpResponse.write("</br>")
httpResponse.write("*************************");
}
else
{
httpResponse.write(stdout);
httpResponse.write("</br>")
httpResponse.write("*************************");
}
count = count + 1;
console.log('count = ' + count);
if (count === 7)
{
console.log('ending the response');
httpResponse.end();
}
});
})(count); // end of closure function
console.log(ips[i]);
}
Running this will get you the output:
count = 1
count = 1
count = 1
count = 1
count = 1
count = 1
count = 1
Related
This is a really unusual code i haven't written myself, each day a database is updated with around 200 records.
This means we have to do 200 api calls to figure out infomation about theese records every day at 7 am.
This has been working fine until now,
the api has implemented a limit of 50 api calls pr hour, and IF you try to do 51 calls, you get banned for 24 hours...
SO, how do i make the for loop do a maximum of 50 loops here?
for (let record of records ) {
//This loop has to be limited to 50 iterations pr run.
let brregRawData = await fetch(`some url/${record.name}/someurl`);
let brregJson = await brregRawData.json()
let personNavn = brregJson.rollegrupper[0].roller[0].person.navn.fornavn
let personEtternavn = brregJson.rollegrupper[0].roller[0].person.navn.etternavn
// if mellomnavn = undefined, then do nothing
if (brregJson.rollegrupper[0].roller[0].person.navn.mellomnavn == undefined) {
var personMellomNavn = ""
} else {
let personMellomNavn = brregJson.rollegrupper[0].roller[0].person.navn.mellomnavn + " "
}
I tried looking up different ways to use a for loop, but all the solutions i looked at broke the "${record.name}" part of the url, i have to loop through an entire view of an entire database.
I'm not sure if this is right for the case, but can you define a counter outside of the loop, increment internally and break when it reaches 50.
let count = 0;
for (....)
...
if (count++ > 50) break;
...
If I'm understanding you correctly, you need to limit the number of api calls to 50 but the current implementation uses a for ... of loop. The simplest way to achieve what you're looking for with the least amount of modification is to use a standard for loop.
Assuming this all happens inside an async function...
async function limitToFiftyApiCalls(records) {
const max = Math.min(records.length, 50);
for (let i = 0; i < max; i++) {
const record = records[i];
let brregRawData = await fetch(`some url/${record.name}/someurl`);
let brregJson = await brregRawData.json();
let personNavn = brregJson.rollegrupper[0].roller[0].person.navn.fornavn;
let personEtternavn = brregJson.rollegrupper[0].roller[0].person.navn.etternavn;
// if mellomnavn = undefined, then do nothing
if (brregJson.rollegrupper[0].roller[0].person.navn.mellomnavn == undefined) {
var personMellomNavn = "";
} else {
let personMellomNavn = brregJson.rollegrupper[0].roller[0].person.navn.mellomnavn + " ";
}
}
}
The code above doesn't modify your existing code much other than limiting the number of API calls. However there's a few things you could do that would generally make the code easier to read and edit.
async function limitToFiftyApiCalls(records) {
const max = Math.min(records.length, 50);
for (let i = 0; i < max; i++) {
const record = records[i];
let personMellomNavn = "";
let brregRawData = await fetch(`some url/${record.name}/someurl`);
let brregJson = await brregRawData.json();
// why write this more than once?
// save it to a variable and make life easier
let someVar = brregJson.rollegrupper[0].roller[0].person.navn;
let personNavn = someVar.fornavn;
let personEtternavn = someVar.etternavn;
if (someVar.mellomnavn) {
personMellomNavn = someVar.mellomnavn + ' '
}
}
}
A very simple way to do this is implementing a count that increments every time the loop executes the body. So for the the loop you provided it would look like this:
let count = 0; // initialize count as 0
for (let record of records ) {
if(count >= 50) break; // break out of loop if count is equal to or greater than 50 (since count starts from 0)
//This loop has to be limited to 50 iterations pr run.
let brregRawData = await fetch(`some_url/${record.name}/some_url`);
let brregJson = await brregRawData.json()
let personNavn = brregJson.rollegrupper[0].roller[0].person.navn.fornavn
let personEtternavn = brregJson.rollegrupper[0].roller[0].person.navn.etternavn
// if mellomnavn = undefined, then do nothing
if (brregJson.rollegrupper[0].roller[0].person.navn.mellomnavn == undefined) {
var personMellomNavn = ""
} else {
let personMellomNavn = brregJson.rollegrupper[0].roller[0].person.navn.mellomnavn + " "
}
count++; // Increment the count after each iteration
}
Answer to you question:
for (let i=0; i<math.min(records.length, 50); i++ ) {
let record = records[i];
But what happens then with the records you have not checked? Will you wait 24h? I guess that's not what's expected, and instead will have to check 50 records every hour until you have checked them all (so 4 times for 200 records).
I am attempting to write a dealer function for a card game, I want the function to keep its i value each time its called, so that that the card pile( player1Deck and player2Deck) gets smaller and smaller till empty. currently the i value looks like it will reset each time the function is called how can I stop this.
I am very new to all of this.
function dealOut(){
for (let i = 0; i < player1DeckHandcells.length; i++) {
const cell = player1DeckHandcells[i];
cell.appendChild(player1Deck.cards[i].getHTML)
}
for (let i = 0; i < player2DeckHandcells.length; i++) {
const cell = player2DeckHandcells[i];
cell.appendChild(player2Deck.cards[i].getHTML)
}
}
More information
Each dealout call should make i increase by 7. this means we are on the 8th "card"(player1Deck.cards[i].getHTML and player2Deck.cards[i].getHTML) in the "deck"( player1Deck and player2Deck)and there should be a total of 28 cards with 21 left to go. I want the i value to count through these "cards", so it doesn't just repeat the first 7 every time dealout is called.
You can use a closure (a function that keeps a copy of the outer variables). We can use that function for dealOut. Note: arrays are zero-indexed so i starts at 0 not 1.
function loop() {
// Maintain a count
let count = 0;
// Return a function that we actually use
// when we call dealOut. This carries a copy
// of count with it when it's returned that we
// can update
return function () {
const arr = [];
// Set i to count, and increase until
// i ia count + 7
for (let i = count; i < count + 7; i++) {
arr.push(i);
}
console.log(arr.join(' '));
// Finally increase count by 7
count += 7;
}
}
const dealOut = loop();
dealOut();
dealOut();
dealOut();
dealOut();
How does counting instances of a callback function work in node.js?
I was working on the 9th exercise of learnyounode (below the official solution).
As I understand it, the httpGet function is called three times, running through process.argv[2], [3] and [4]. But how could count ever === 3? Don't the individual functions just get to one? How does one call of httpGet know of the other ones?
var http = require('http')
var bl = require('bl')
var results = []
var count = 0
function printResults () {
for (var i = 0; i < 3; i++)
console.log(results[i])
}
function httpGet (index) {
http.get(process.argv[2 + index], function (response) {
response.pipe(bl(function (err, data) {
if (err)
return console.error(err)
results[index] = data.toString()
count++
if (count == 3)
printResults()
}))
})
}
for (var i = 0; i < 3; i++)
httpGet(i)
But how could count ever === 3?
count is defined outside of httpGet and thus its value is independent of the those function calls. count++ is the same as count = count + 1, i.e. every call to httpGet increases the value of count by 1. The third time the function is called, count's value will be 3.
We can easily replicate this:
var count = 0;
function httpGet() {
count++;
console.log('count: ', count);
if (count === 3) {
console.log('count is 3');
}
}
httpGet();
httpGet();
httpGet();
First, prefer not using var.
var is defined in the global scope so it’s value updated between calls
Read more about var here
I want to get data from a sensor in milliseconds and then calculate the average value within ten seconds to alert based on the average value. The problem is that this code runs well as long as the while loop been set to less than 1000 or one second and when I set it to larger numbers(I want the loop to work infinitely and stop with a button function). I want to know if there any way to function this infinite loop in Javascript?
Here is my code:
const now = Date.now();
var epochTime = now;
//Arrey of the value
var Arrey = [];
Counter =0
while (epochTime<now+10000000) { //should be set infinite and stop with button
$.get('http://xxx/'+epochTime, function(data){
let myValue= data.data[354708094967841].crosscorrelations[0].value;
document.getElementById("demo").innerHTML +="<br/>"+ myValue ;
Arrey.push(myValue);
console.log(Arrey);
var sum =0;
console.log(epochTime);
if (Counter>=10000 && Counter%10000==0){
for ( i=Counter-10000; i<Counter; i++)
sum = sum + Arrey[i];
valueAverage= sum/10000;
console.log(valueAverage);
document.getElementById("valueAverage").innerHTML +="<br/>"+ valueAverage;
if (valueAverage>0.01){
alert("the value ave is high"); // ----> to check the code
}else{
alert("the value ave is low"); //-----> to check the code
}
}
console.log(Counter);
Counter++;
console.log(myValue); //get data from value in async version
});
epochTime ++;
}
As the comments said: $.get() is asynchronous, so it doesn't wait. What you could do, is wrap the get request in a function and call the function from within the request, thus creating a loop. So sort of like this:
var buttonClicked = false;
//Function simply wraps the get request so that it can be called at anytime
function getSensorData(){
$.get('http://xxx/'+epochTime, function(data){
let myValue = data.data[354708094967841].crosscorrelations[0].value;
document.getElementById("demo").innerHTML += "<br/>" + myValue;
Arrey.push(myValue);
console.log(Arrey);
var sum = 0;
console.log(epochTime);
if (Counter >= 10000 && Counter % 10000 == 0) {
for (i = Counter - 10000; i < Counter; i++)
sum = sum + Arrey[i];
valueAverage = sum / 10000;
console.log(valueAverage);
document.getElementById("valueAverage").innerHTML += "<br/>" + valueAverage;
if (valueAverage > 0.01) {
alert("the value ave is high"); // ----> to check the code
} else {
alert("the value ave is low"); //-----> to check the code
}
}
console.log(Counter);
Counter++;
console.log(myValue); //get data from value in async version
//Now that you're done with everything, you can check if the button is clicked and if it is, don't run the function again.
if (!buttonClicked){
getSensorData();
}
}
}
//Here we check if the button is clicked and change the variable when it is
$("#stopButton").click(function(){
buttonClicked = true;
});
Also, quick note: Variables in javascript are usually camelCase, not Capitalized; constants are the exception because they are generally ALLCAPS.
I'm struggling on how to increment a basic counter in javascript.
What do I want to achieve ?
I need a counter inside a foreach loop. The goal is to be able to count each time the //Write smthg is triggered.
Below is the updated version of the code I'm using. For the moment, it returns weird sequences of numbers. I guess it is resetted each time the recursive loop is triggered. I do not know how to correct it, suppose it's a basic javascript problem but as I'm learning through experimenting and on my own, I sometimes need to ask question to the community.
function walk(dir, counter = 0) {
fs.readdirSync(dir).forEach(file => {
let fullPath = path.join(dir, file);
if (fs.lstatSync(fullPath).isDirectory()) {
counter = walk(fullPath, counter);
walk(fullPath, counter);
console.log('dir');
} else {
let size = fs.statSync(fullPath).size; // Get size of file
listFiles.write(fullPath + " (" + size + ")\n"); // Write file path and size into copyList.xml
++counter;
console.log(counter);
}
});
return counter;
}
walk(copyFrom); // Starts function "walk"
Sequences obtained :
2,3,4,5,6,7,dir,5,6,8,9,10,11,12,13,dir,11
Here is the complete answer
function walk(dir) {
let n = 0;
function walk(dir) {
fs.readdirSync(dir).forEach(file => {
++n;
console.log(n);
let fullPath = path.join(dir, file);
if (fs.lstatSync(fullPath).isDirectory()) {
--n;
walk(fullPath);
console.log('dir');
} else {
let size = fs.statSync(fullPath).size; // Get size of file
listFiles.write(fullPath + " (" + size + ")\n"); // Write file path and size into copyList.xml
}
});
}
return walk(dir);
}
Use a helper. The function walk makes the lexical variable n and a function walk that shadows the called fucntion for the duration of the recursive calls. It may have the original content of walk and the outer function just returns the result of calling it as itself was called.
function walk(dir) {
let n = 0; //Counter variable
function walk(dir) {
dir.forEach(file => {
++n;
console.log(n);
if (true) {
//Recurse loop
} else {
//Write smthg
}
});
}
return walk(dir);
}
So, your issue is as follows:
Your counter will reset to 0 each time you recurse. So your numbers can go something like so: 0, 1, 0, 2, 0, 1, 2, 3, 3, ...etc. If you want to have an iterator counting total number of iterations, you'll need to pass your counter into the function and default it to 0 (for the first time walk is called), like so:
var files = ["dir1-file1", "dir1-file2", ["dir1-sub1-file1"], "dir1-file3", ["dir1-sub2-file1", ["dir1-sub2-subsub1-file1"]]];
function walk(dir, counter = 0) {
dir.forEach(file => {
if (Array.isArray(file)) {
// pass counter in to recursed function call
// set current function counter to the result of the recursed function calls
counter = walk(file, counter);
} else {
//Write smthg
++counter;
console.log(counter);
console.log(file);
}
});
// return the counter for parent
return counter;
}
walk(files);