Javascript global variable not updating - javascript

I am trying to access the dataCount variable from another file after its been updated by updateData function which takes an array as a parameter and as the pop function returns the new length I have passed that directly to the updateStatus function.
But even after updating it and accessing it stills gives me 0.
// status.js file
var dataCount = 0;
let data = []
function updateStatus(num, opp){
if (opp == "add"){
dataCount += num
} else if (opp == "sub") {
dataCount -= num
} else {
dataCount = num;
}
}
function updateData(arr){
updateStatus(data.push(arr), 'update');
}
module.exports = {
dataCount: dataCount,
updateStatus: updateStatus,
data: data,
updateData: updateData
}
// middleware.js file
const status = require('./status');
const methods = require('./helperFunctions')
class Middleware{
constructor(){
}
async populateIfLess(req, res, next){
if (status.dataCount < 4){
try {
// Fetches the data from database and stores in data
const data = await methods.fetchMeaning();
Object.entries(data).map(entry => {
status.updateData([entry[0], entry[1]])
})
methods.log('Data populated on')
setTimeout(() => {
console.log(status.dataCount)
}, 1500);
next()
} catch (error) {
methods.log(error);
res.send({ERROR: "Something went wrong, please check log file."}).end()
}
}
}
}

You are copying the value of dataCount (which is a number so is a primitive) to a property of an object, then you are exporting the object.
Later you update the value of dataCount which has no effect on the object because numbers are primitive (and not handled by reference).
You need to modify module.exports.dataCount instead.

Related

How can I insert attributes of an object from an array of objects into SQLServer using Node JS?

I made a question a minutes ago that I could solve but now I'm having another problem with my code, I have an array of objects lstValid[]and I need each object to be inserted into a table (using a SP) and I though of a way to made it reading documentation but it's not working, maybe it's just a fool mistake but I don't know how to solve it, my mistake is
TypeError: Cannot read properties of undefined (reading 'Id_Oficina')
as you can see, it executes my SP but it says the attribute Id_Oficina is undefined, do you know why is undefined? why is it reading the array but not the attribute?
Here is the function where I create the objects and insert them into the array:
async function calcWeather() {
const info = await fetch("../json/data.json")
.then(function (response) {
return response.json();
});
for (var i in info) {
const _idOficina = info[i][0].IdOficina;
const lat = info[i][0].latjson;
const long = info[i][0].lonjson;
const base = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${long}&appid=${api_key}&units=metric&lang=sp`;
fetch(base)
.then((responses) => {
return responses.json();
})
.then((data) => {
var myObject = {
Id_Oficina: _idOficina,
Humedad: data.main.humidity,
Nubes: data.clouds.all,
Sensacion: data.main.feels_like,
Temperatura: data.main.temp,
Descripcion: data.weather[0].description,
};
// validation and saving data to array
if (myObject.Temperatura < 99)
lstValid.push(myObject);
});
}
}
and here's the function where I insert into DB:
import { Request } from "tedious";
import { TYPES } from "tedious";
function executeStatement() {
calcWeather();
for (var m = 0; m >= lstValid.length; m++) {
const request = new Request(
"EXEC USP_BI_CSL_insert_reg_RegistroTemperaturaXidOdicina #IdOficina, #Humedad, #Nubes, #Sensacion, #Temperatura, #Descripcion",
function (err) {
if (err) {
console.log("Couldn't insert data: " + err);
}
}
);
request.addParameter("IdOficina", TYPES.SmallInt, lstValid[m].Id_Oficina);
request.addParameter("Humedad", TYPES.SmallInt, lstValid[m].Humedad);
request.addParameter("Nubes", TYPES.SmallInt, lstValid[m].Nubes);
request.addParameter("Sensacion", TYPES.Float, lstValid[m].Sensacion);
request.addParameter("Temperatura", TYPES.Float, lstValid[m].Temperatura);
request.addParameter("Descripcion", TYPES.VarChar, lstValid[m].Descripcion);
request.on("row", function (columns) {
columns.forEach(function (column) {
if (column.value === null) {
console.log("NULL");
} else {
console.log("Product id of inserted item is " + column.value);
}
});
});
connection.execSql(request); // connection.execSql(RequestB);??
}
request.on("requestCompleted", function (rowCount, more) {
connection.close();
});
}
I also tried sending them this way but doesn't work either:
request.addParameter("IdOficina", TYPES.SmallInt, lstValid[m].myObject.Id_Oficina);
The problem seems to be a bad condition at the line of
for (var m = 0; m >= lstValid.length; m++) {
This loop initializes m with 0 and increments it while it's greater or equal with the number of elements lstValid has. Since Javascript is a 0-indexed language, lstValid.length is always an invalid index. Valid indexes fulfill this formula
0 <= valid index < lstValid.length
Since your condition checks whether the index is invalid and only then iterates the loop, it will error out at the first iteration if lstValid is empty and it will not execute at all when lstValid is not empty.
Fix
for (var m = 0; m < lstValid.length; m++) {
Explanation
Your error came from the fact that lstValid.length was 0, m was 0 and your code attempted to process member fields of the first element of an empty array. Since there was no first element in the speicifc case, it errored out.

Await Async when looping through large json file

The json file is large around 20mb.
I want to wait until a result is returned or the entire file is looped through, before sending back the age. Currently it returns 0 even if the age is not 0
const app = express()
const genesis = require('./people.json');
app.get('/', function (req, res) {
res.setHeader('Content-Type', 'application/json');
let age = getAge(req.query.name)
res.json({
“name”: req.query.name,
“age”: age, // this is always 0
});
});
function getAge(name) {
genesis.balances.forEach(element => {
if (element.name == name) {
// console here shows correct age
return element.person[0].age;
}
});
return 0;
}
app.listen(3000)
As I said in the comment, the problem was in your getAge method, it was always returning 0.
The return inside the forEach doesn't return the value off of the loop.
Please have a look at the following approach
function getAge(name) {
const person = genesis.balances.find((elm)=> elm.name === name);
return person ? person.age : 0;
}
See code comment below
function getAge(name) {
genesis.balances.forEach(element => { // forEach doesn't return anything
if (element.name == name) {
// console here shows correct age
return element.person[0].age;
}
});
return 0;
}
You probably want instead something like:
function getAge(name) {
const res = genesis.balances.filter(element => element.name == name);
if (res.length === 0) return 0; // not found
return res[0].person[0].age;
}
read more about forEach
Comment: having a person-array under element with "name" is a weird choice, why should a single person-name be mapped to multiple persons?

botpress - increment vlaue

I am trying to get a custom action running to simply incrementing a value on passing a specific node on the flow.
My custom actions looks like this:
function action(bp: typeof sdk, event: sdk.IO.IncomingEvent, args: any, { user, temp, session } = event.state) {
/** Your code starts below */
let i = undefined
const p = new Promise((resolve, reject) => {
if (i === undefined) {
resolve((i = 0))
} else if (i >= 0) {
resolve(i + 1)
} else {
reject('i cannot be < 0')
}
})
const runCount = async () => {
try {
const counter = await p
i = counter
return (session.count = counter)
} catch (err) {
console.log(err)
}
}
return runCount()
/** Your code ends here */
}
When I runCount() variable i will be set to 0. But then, after in rerun runCount() it does not increment further.
What do I need to do to save the variable so it increments on every runCount() call.
Greetings
Lorenz
I just managed to solve the problem.
I had to declare i = session.count at the beginning.
Now it gets the value out of the session state and increments the state on every call.
Maybe someone gets some help out of this.
Lorenz

How to call async function to use return on global scope

I'm currently struggling with a function call, when I call the function from an if statement it does work but when I call it from outside it doesn't, my if statement only checks which button was pressed but I'm trying to remove the function from the button and just call it as soon as my app starts.
We will look at fetchJokes() inside jokeContainer.addEventListener('click', event => {
This is my current code:
const jokeContainer = document.querySelector('.joke-container');
const jokesArray = JSON.parse(localStorage.getItem("jokesData"));
// Fetch joke count from API endpoint
async function sizeJokesArray() {
let url = 'https://api.icndb.com/jokes/count';
let data = await (await fetch(url)).json();
data = data.value;
return data;
}
// use API endpoint to fetch the jokes and store it in an array
async function fetchJokes() {
let url = `https://api.icndb.com/jokes/random/${length}`;
let jokesData = [];
let data = await (await fetch(url)).json();
data = data.value;
for (jokePosition in data) {
jokesData.push(data[jokePosition].joke);
}
return localStorage.setItem("jokesData", JSON.stringify(jokesData));;
}
const jokeDispenser = (function() {
let counter = 0; //start counter at position 0 of jokes array
function _change(position) {
counter += position;
}
return {
nextJoke: function() {
_change(1);
counter %= jokesArray.length; // start from 0 if we get to the end of the array
return jokesArray[counter];
},
prevJoke: function() {
if (counter === 0) {
counter = jokesArray.length; // place our counter at the end of the array
}
_change(-1);
return jokesArray[counter];
}
};
})();
// pass selected joke to print on html element
function printJoke(joke) {
document.querySelector('.joke-text p').textContent = joke;
}
sizeJokesArray().then(size => (length = size)); // Size of array in response
jokeContainer.addEventListener('click', event => {
if (event.target.value === 'Fetch') {
fetchJokes(length);
} else if (event.target.value === 'Next') {
printJoke(jokeDispenser.prevJoke(jokesArray));
} else if (event.target.value === 'Prev') {
printJoke(jokeDispenser.nextJoke(jokesArray));
}
});
And I'm trying to do something like this:
// pass selected joke to print on HTML element
function printJoke(joke) {
document.querySelector('.joke-text p').textContent = joke;
}
sizeJokesArray().then(size => (length = size)); // Size of array in response
fetchJokes(length);
jokeContainer.addEventListener('click', event => {
if (event.target.value === 'Next') {
printJoke(jokeDispenser.prevJoke(jokesArray));
} else if (event.target.value === 'Prev') {
printJoke(jokeDispenser.nextJoke(jokesArray));
}
});
By the way, I'm aware that currently, you can't actually iterate through the array elements using prev and next button without refreshing the page but I guess that will be another question.
Couldn't think of a better title.(edits welcomed)
Async functions are, as the name implies, asynchronous. In
sizeJokesArray().then(size => (length = size)); // Size of array in response
fetchJokes(length);
you are calling fetchJokes before length = size is executed because, as you may have guessed, sizeJokesArray is asynchronous.
But since you are already using promises the fix is straightforward:
sizeJokesArray().then(fetchJokes);
If you have not fully understood yet how promises work, maybe https://developers.google.com/web/fundamentals/getting-started/primers/promises helps.

JS Array allways returns undefined and length = 0

(using Node.js)
Hi, I have an array with users (User class) on it, when I print the array with console.log, it shows the content correctly and shows that it's length is 3, but when i try to get any thing from the array, it returns undefined and for *.length, it returns 0. Where's the problem?
exports.users = [];
exports.loadUsers = (callback) => {
let more = true;
let i = 0;
while(more) {
let us = _usersFolder + "us_" + i + "/";
if(fs.existsSync(us)) {
fs.readFile(path.join(us + "personal.json"), (err, data) => {
if(err) {
console.log("failed to load file!");
return;
}
let json_personal = JSON.parse(data);
this.users.push(new User(json_personal));
});
i++;
} else {
more = false;
}
}
callback();
}
exports.getUserById = (id) => {
console.log(this.users);
console.log("length: " + this.users.length);
console.log(this.users[0]);
for(let i = 0; i < this.users.length; i++) {
let u = this.users[i];
console.log(u.id);
if(u.id === id) {
return u;
}
}
return false;
}
getUserById is called in the callback, so users are already loaded.
It depends on where you are using the 'this' object. It's possible that 'this' makes reference to a different object than the one you stored the array in ('this' varies depending on the scope where you are using it).
I'd need more information to help you.
var users=[{"num":1},{"num":2},{"num":3}];
console.log(this.users);
console.log("length: " + this.users.length);
console.log(this.users[0]);
output
(3) [Object, Object, Object]
length: 3
Object {a: 1}
I hope you are defining after you print in console.
var users = [];
console.log(users);
console.log("length: " + users.length);
console.log(users[0]);
users.push(1);
users.push(2);
users.push(3);
The output of console.log() is misleading; While you log that time there was no value. After that it was added. It prints the reference of object , not the state value. So you will see current state value all the time.

Categories