Defining variable as let and var showing NaN - javascript

I am using a variable like below :
var maxId=1;
schema.table.max('id').then(function(max) {
maxId=max+1;
}).catch(err => {
maxId=1;
});
to take the maximum id from the DB and add one.
console.log(maxId) //prints the maximum id.
I also want to add the new id for the new data by below :
schema.table.findAll({where: option}).then((existed) => {
for (let insert of insertionList) {
insert['id'] = maxId;
maxId=maxId+1;
}
})
Here insertionList's id attribute is showing as NaN instead of the max .
I used let and var but both resulted in NaN. Any help is appreciated.

This is a generic answer, not only based on what you wrote.
It will help you to debug your problem and write more concise code.
Declaring a variable somewhere and change it within a promise is a very bad practice, you can create something unpredictable and it can be based on race conditions.
Your variable at the time you read it can be easily undefined or something. It's all based on timing.
Something like:
var maxId=1;
schema.table.max('id').then(function(max) {
maxId=max+1;
}).catch(err => {
maxId=1;
});
can be easily translated to:
const maxId = await schema.table.max('id')
.then(max => {
// here some checks on max (can it be null or undefined?)
return max + 1;
}, () => 1);
To avoid side effects try to use "const" as much as you can instead of "let" and "var". If you are forced to use let or var in most of cases means you are doing it wrong especially when you use promises or async code.
An important consideration....
What you wrote implies that an error would consider max == 1. Throwing an error (or reject a promise) should be handled in a proper way (and not like your example, not even like in mine...). The library you use probably would reject your promise in case of an I/O issue or a lack of permission. Those cases shouldn't imply max = 1 but they should be reported in order to take additional actions.

undefined + 1
=> NaN
I think that when your db is empty, it wont pass by your catch statement because there had been no error trying to get the max value (even if it is undefined).
You should handle the case of max being undefined.
Here is my solution written in ES6:
let maxId = 1;
schema.table.max('id')
.then(max => maxId = (max || 0) + 1)

Related

Sequelize.fn : Constructing the update argument outside the call

Issue Description
I'm currently trying to make updates on passwords using sequelize.fn.
I've seen numerous sites, including the Sequelize's manual, yet I found too few articles that approaches my case, and none of them seems to solve it.
Moreover, the function to encrypt the passwords need nested function, so I need to gradually construct the nested function
by putting the successive arguments into variables.
I have not found anything on constructing the functions, thus using sequelize.fn outside the arguments of the functions find and updates.
Additional context
In my case, " crypt('password', gen_salt('bf', 4)) " (in Postgres) needs to become
sequelize.fn('crypt', 'password', sequelize.fn('gen_salt', 'bf', 4)) and to be stored into a variable
When I inject it into the update function, an Fn Object is injected, and the result in the database seems to be a memory address instead of the result of the crypt function.
I may post a code example so you can have a better understanding of what I'm trying to do and I think should be added into the documentation
I did not made this doc issue to resolve my issue, only to point out what I think is lacking in the documentation
I will ask StackOverflow for help regarding my issue.
//Take a format and a value, and applies the functions inside the format onto the value
function recursSequelizeFn (format, value) {
const sequelize = db.sequelize;
let nextId = 0;
let matches;
let finalArgs = {};
//The RegEx finds the function calls of which parameters aren't functions themselves
//As the format string is modified on each loop, I need to initialize the RegEx on each loop
while ((matches = (/(\w+)\(([^(,)]+)?(?:,([^(,)]+))*\)/g).exec(format)) !== null) {
//matches[0] is the whole expression
//matches[1] is the function's name
//matches[>=2] are the arguments
let func = matches[1];
let args = matches.slice(2);
for (let argNo in args) {
//Transforms DB's columns into Sequelize-interpreted columns
//I do not check the column that is found, because I do not have others columns than the one that is being treated
args[argNo] = args[argNo].replace(/seqCol_(\w+)/g, (correspondance, p1, decalage, chaine)=>{return value;});
//If the parameter was previously saved, we replace its reference by its value
args[argNo] = args[argNo].replace(/(#\d+)/g, (correspondance, p1, decalage, chaine)=>{return finalArgs[p1];});
}
//finally, we save the value of the function and replace the whole expression by a reference
finalArgs['#'+nextId]=sequelize.fn(func, ...args);
format = format.replace(matches[0], '#'+nextId);
nextId++;
}
//When the treatment is finished, we return the last value saved into the array
//Or we return the original value if we have not made any change (the array will be empty)
return finalArgs['#'+(nextId-1)]||value;
}
Object.keys(req.message.attributes).map((key)=>{
//req.message.attributes[key] contains the formatting needed to be put onto the value
//e.g. crypt(password, gen_salt('bf', 4))
//req.body[key] contains the value
//e.g. '1234'
let seqValue = util.recursSequelizeFn(req.message.attributes[key], req.body[key]);
req.body[key] = seqValue;
});
//mainModel is a sequelize model
mainModel.update(req.body, {where: {id:req.params.id}, logging:console.log})
.then() //...

Correct Syntax For Using The Returned Variable From A Function?

I have a function that returns a variable, I'd just like to know what's the correct syntax for doing something (such as doing math or writing a new variable using that returned variable.
Example Function:
function exampleFunction(number) {
var data_filter = number + number;
return data_filter;
}
The function returns data_filter, and I'd like to know what's the correct syntax for doing something with it, such as inputting it in another function.
What you have here is fine.
As one of the comment suggests typically you assign the result to a variable. Take a simple example here:
let myNumber = 10;
let myHalvedNumber = halveNumber(myNumber);
console.log(myNumber)
console.log(myHalvedNumber);
function halveNumber(numberToHalve){
return numberToHalve/2;
}
The best way to think about it in practice is to treat the function/input combination { f(x) } as a proxy for the result itself. This means that both of these examples are correct and how you choose to employ it is your own preference.
//These two approaches are identical and both valid:
//1) Assign to a variable for further use - typically better for variable re-use:
let myHalvedNumber = halveNumber(10);
aSecondFunction(myHalvedNumber);
//2) Use the result directly in a second call - typically shorter and arguably easier to maintain/read
aSecondFunction(halveNumber(10));
function halveNumber(myNumber){
return myNumber/2;
}
function aSecondFunction (myNumber){
console.log("the number is: " + myNumber)
}

JavaScript for loop not executed although valid array provided

Trouble finding the reason why JavaScript for loop is not executing. Wrote 2 simple functions below that I want to execute and run i.e.: Bought method should try to "simulate" synchronous code.
The problem is that for some reason the for loop in the addNodes() method is never executed. However, if I run this separately i.e. for example line by line
var result = [];
var addressBookNodes = await generateAddressBooksNodes();
addNodes(result, addressBookNodes);
that tells me that the code is running fine however most likely it has something to do with the asynchronous nature of the generateAddressBooksNodes method. If I simply run the command :
var addressBookNodes = await generateAddressBooksNodes();
in the browser, I get an array of objects exactly what I was expecting to get. Basically the generateAddressBooksNodes returns a promise and when that promise is resolved I can see the correct array returned however what I do not understand why the for loop is not executed if the nodes objects have at least one element as shown in the picture below.
function addNodes(result, nodes){
console.log("3");
console.log(nodes);
for (var num in nodes) {
console.log("4");
let singleNode = nodes[num];
console.log(singleNode);
console.log("5");
result.push(singleNode);
}
}
async function getAddressBookAndContactNodes() {
var result = [];
console.log("1");
var addressBookNodesPromise = generateAddressBooksNodes();
addressBookNodesPromise.then( (arrayOfAddressBookNodes) => {
console.log("2");
addNodes(result, arrayOfAddressBookNodes);
})
return result;
}
Update 26 August 2020 :
After poking around the "arrayOfAddressBookNodes" object i noticed something really strange. I added additional print statement and printed the length of the "arrayOfAddressBookNodes" array. The length of the array is 0 when runned in the function. I do not understand how the length can be 0 if the object is printed shortly before the for loop and as shown on the picture below the length there is :1. What the hell is going on here?
I found another article i.e. JavaScript Array.length returning 0 that is basically explaining this. And in one of the commends it has been mentioned to use Map instead of an Array. I decided to use Set, and still get the same error i.e. the size of the set is 0 although the Set contains an object. i.e. below is the code and the picture of that execution.
async function getAddressBookAndContactNodes() {
var result = new Set();
console.log("1");
var addressBookNodes = await generateAddressBooksNodes();
console.log("2");
console.log(addressBookNodes);
console.log("3");
console.log("addressBookNodes size : " + addressBookNodes.size);
addressBookNodes.forEach(function(value) {
result.add(value);
});
console.log("6");
console.log(result);
console.log("7");
return result;
}
example using set
all this is really confusing to someone having a c++ backgroud, it makes my head explode.
Update 2 : 26 August 2020.
Ok i solved my problem. The problem was that the the promises are not working withing the for loop everything is explained here.
i need to use the regular "for (index = 0; index < contactsArray.length; ++index) " instead of foreach. after that it all worked. Somehow this leaves the impression that the tools of the language are broken in so many ways.
If generateAddressBooksNodes is returning a promise, you can use async to wait for the results:
async function getAddressBookAndContactNodes() {
var result = [];
console.log("1");
var addressBookNodesPromise = await generateAddressBooksNodes();
// note await here. Also, unless you're using this at a later time in your code, you can save space by not assigning it to a variable and simply returning generateAddressBooksNodes
addNodes(result, arrayOfAddressBookNodes);
return result;
}

Is it possible to use .reduce with a const?

I was completing an assignment in my coding bootcamp. They asked us to use .reduce to come up with a value. However, they initialized the total value using a const variable. When I would try to solve this problem using the const value, it kept throwing errors.
Because in my head, you can't change the const value. I simply replaced const with let. I'm not sure if I was supposed to change the code in that way but that's what I did.
const populationTotal = 0;
populationTotal = zooAnimals.reduce((total, item) => total + item.population, 0);
console.log(populationTotal);
If I keep the code the way it is, (const populationTotal = 0), it throws an error. When I changed the code (let populationTotal = 0), the problem was solved. Am I correct in thinking that you have to change const to let. Or is there a way to solve this problem with a const initial value?
Am I correct in thinking that you have to change const to let.
Yes, if you want to mutate the variables value after declaration.
Or is there a way to solve this problem with a const initial value
Sure. You can choose another initial value instead of 0.
const populationTotal = /* calculate the result here */;

Confusion on Private Method Using or Not-using function

I didn't take any official course of Javascript.
I often read this in tutorials:
function Bank(name) {
this.name = name;
var balance = 100;
// *my question here* method to access balance
this.getBalance = function() {
return balance * 0.9 ;
};
}
var myBank = new Bank("My Bank");
console.log( myBank.getBalance() );
Why do developers use getBalance() instead of getBalance?
I think "getBalance" is easier to read, but no tutorial use this:
// *my question here* method to access balance
this.getBalance = balance * 0.9 ;
then
console.log( myBank.getBalance );
I didn't see any tutorial to write using above style, even it is simpler. So:
Is there any different between 2 style of codes? Is there any concern to avoid .getBalance to operate the private variable?
Thanks in advance to explain.
You must understand the different between variable, function and function call. This is variable:
this.getBalance = balance * 0.9 ;
The value of getBalance variable is computed once when the code is executed. Every time you access getBalance (without parentheses), previously computed value is returned.
There is an important implication of using getBalance variable. If you modify underlying balance variable in the future, getBalance won't reflect that change because it was computed using old balance value.
In the case below:
this.getBalance = function() {
return balance * 0.9 ;
};
getBalance is also variable but it points to a function, not to a simple value. If you access it like variable, you will get a function reference:
var fun = this.getBalance
You can now call that function using fun(), but fun reference itself (same as this.getBalance) isn't very useful in your case.
And of course you can call the function by using this.getBalance(). The semantic difference is as follows: every time you call getBalance(), the body of the function is executed. This means the value of balance is read again and getBalance() return value is always up to date.
As you can see there is a huge difference between assigning a function and assigning a simple value (like number) to a variable. Depending on which approach you choose, it will have different implications. You must learn about functional side of JavaScript in order to fully utilize its power.

Categories