Variables Not Being Retained - javascript

Alrighty.
My problem is with the Javascript Objects itemList and priceList - they are not retained properly into the .then() section.
Here's the part that I'm having trouble with:
var stmt = `SELECT * FROM SRV${msg.guild.id}`;
var itemList = {};
var priceList = {};
var num = -1;
sql.each(stmt, function(err, row) {
num++
if(row.items!="ITEMS") { itemList[num] = row.items; }
if(row.prices!="PRICES") { priceList[num] = row.prices; }
console.log("---------\n" + JSON.stringify(itemList, null, 4) + "\n" + JSON.stringify(priceList, null, 4));
})
.then((itemList, priceList) => {
console.log("----E----\n" + JSON.stringify(itemList, null, 4) + "\n" + JSON.stringify(priceList, null, 4) + "\n----E----");
let cmd = require("./itemsPROCESS.js");
cmd.run(transfer, msg, args, itemList, priceList);
});
And here's the important bit that it outputs:
I've tried using strings instead of Javascript Objects, but it doesn't seem to like that either, and it outputs the same.
The 5 and undefined part should resemble the bit above it, but it doesn't.
Might it have something to do with the null parts? If so, will that mean it won't work with true - false - undefined etc?

remove the arguments itemList and priceList and your code should just be fine.
The itemList you are referring inside the .then function is actually what is resolved by the SQL promise.
.then(() => {...});

You are using itemList and priceList of global scope so don't redefine them in local scope of then. Just remove those arguments from then
.then(() => {
console.log("----E----\n" + JSON.stringify(itemList, null, 4) + "\n" + JSON.stringify(priceList, null, 4) + "\n----E----");
let cmd = require("./itemsPROCESS.js");
cmd.run(transfer, msg, args, itemList, priceList);
});

Related

Why the Code After Array.foreach doesn't execute?

I am trying to get value of a global variable (screenDisplay) after completing the for each portion.
But it seems whenever the 2nd Part is put before the 1st Part, the value that i am supposed to get from screenDisplay comes undefined and the console throws an error.
*error
TypeError: Cannot read properties of undefined (reading 'toFixed')
Why does the screenDisplay's value gets affected when part 2 is kept after part 1?
To find the error directly input values to the screen without using calculator key. ex. (2+3)
Live Link Here
const screenDisplay = document.getElementById("screen-input-selector");
const result = () => {
focusInitiate();
try {
**//1st Part**
// * auto multiplication feature
displaylocalStorageDATA();
const screenItems = [...screenDisplay.value];
let screenPosition = screenDisplay.selectionStart;
screenItems.forEach((item, index) => {
let indexno = index + 1;
if (
screenItems.length != indexno &&
![")", "+", "-", "*", "/"].includes(screenItems[index + 1]) &&
item == ")"
) {
let remainingDataFirstPortion = screenItems.slice(0, index + 1); //selects and stores the rest of the portion of the text after cursor
let remainingDataLastPortion = screenItems.slice(
index + 1,
screenItems.length
);
const clearedArray = remainingDataFirstPortion.concat("*");
const clearedArray1 = clearedArray.concat(remainingDataLastPortion);
screenDisplay.value = clearedArray1.join("");
displaylocalStorageSTORE();
screenDisplay.setSelectionRange(screenPosition, screenPosition);
}
});
//2nd Part
const inputData = localStorage.getItem("display");
if (inputData != null) {
//when inputdata and screendisplay value are same
if (inputData == screenDisplay.value) {
//when local storage has some value
displaylocalStorageREMOVE();
// screenDisplay.value = eval(localStorage.getItem("display"));
screenDisplay.value = Function("return " + inputData)().toFixed(4); //using function constructor instead of EVAL function cause EVAL() executes the code it's passed with the privileges of the caller
displaylocalStorageSTORE();
} else {
//when inputdata and screendisplay value are not same
displaylocalStorageREMOVE();
screenDisplay.value = Function(
"return " + screenDisplay.value
)().toFixed(4);
displaylocalStorageSTORE();
}
} else {
//when local storage is empty
screenDisplay.value = Function("return " + screenDisplay.value)().toFixed(
4
);
displaylocalStorageSTORE();
}
} catch (error) {
console.log(error);
};
Problem Resolved.
displaylocalStorageDATA() (which reassigns locally saved data to the global variable) of Part 1 was causing the problem. It was redefining the screenDisplay.value.
Removing that line has solved the problem.
Thanks, Everyone.

ES6 JavaScript async await not resolving

The following code was an attempt to rework the recursive solution I posted here: How to do a Recursive ES6 Object Mutator.
This one is a simple match and replace, but has the same async dependency.
I have the following json input as a simple tester:
[
{
"name" : "dexterity ability score increase by 1",
"description" : "your dexterity score increases",
"benefit": {
"appliesTo": "$$$StatisticDef|(#name#:#dexterity#,#type#:#ability#)",
"appliesWhen": "ongoing",
"atLevel": 1,
"category": "addition",
"value": 1
}
}
]
Two things to note here:
the value for appliesTo. This is the string that I want to replace
with a MongoDB fetched value (the async dependency).
The structure is an array of 1 value, this is to show that the input
could have many values
I'm running this in the following mocha test, using sinon for mocking (this is not part of this query, it all seems to work, I'm just showing how this is being executed).
describe('FeatureDefAdder suite', function () {
var mock = sinon.mock(StatisticDef)
test('should try again with the linear resolver', async function () {
var queryObjJson = '{"name":"dexterity","type":"ability"}'
mock
.expects('findOne')
.withArgs(JSON.parse(queryObjJson))
.chain('select')
.withArgs('_id')
.chain('exec')
.resolves('5dbff89209dee20b18091ec3')
const data = JSON.parse(
await readFile(
new URL(
'../../../../seeder/character/data/FeatureDef.json',
import.meta.url
)
)
)
const result = await linearMongoObjectResolver(JSON.stringify(data))
// returns data subbed by [object Promise]
console.log('substituted: ' + result)
const objectified = JSON.parse(result)
console.log('objectified: ' + objectified)
console.log('resval ' + objectified[0]['benefit']['appliesTo'])
})
})
and now the matcher code:
const linearMongoObjectResolver = async (data) => {
// assume data is any json screed
// need to find text that matches /"([\$]{3}.*#\))"/ signifying the DSL string /([\$]{3}.*#\))/
// in each case, use the content to pull out the Mongo schema class and the query for the findOne call
console.log(' input data: ' + data)
var copyData = data
// "$$$StatisticDef|(#name#:#dexterity#,#type#:#ability#)"
copyData = await copyData.replace(/([\$]{3}.*#\))/, async (match) => {
//console.log({ match })
var parts = splitForeignKeyReference(match)
var queryObjJson = jsonify(parts[1])
console.log(
' mongoObj: ' +
parts[0] +
' querydsl: ' +
parts[1] +
' queryobjjson: ' +
queryObjJson
)
// query obj = {name: 'dexterity', type: 'ability'}
// console.log(' typeof query is object?: ' + typeof JSON.parse(queryObjJson))
var subbedInstance = '""'
console.log(' 1.subbedInstance: ' + subbedInstance)
if (parts[0] === 'StatisticDef') {
subbedInstance = await StatisticDef.findOne(
JSON.parse(queryObjJson)
).select('_id')
}
console.log(' 2.subbedInstance: ' + subbedInstance)
return subbedInstance
})
return copyData
}
and the (truncated) test output:
input data: [{"name":"dexterity ability score increase by 1","description":"your dexterity score increases","benefit":{"appliesTo":"$$$StatisticDef|(#name#:#dexterity#,#type#:#ability#)","appliesWhen":"ongoing","atLevel":1,"category":"addition","value":1}}]
mongoObj: StatisticDef querydsl: (#name#:#dexterity#,#type#:#ability#) queryobjjson: {"name":"dexterity","type":"ability"}
1.subbedInstance: ""
substituted: [{"name":"dexterity ability score increase by 1","description":"your dexterity score increases","benefit":{"appliesTo":"[object Promise]","appliesWhen":"ongoing","atLevel":1,"category":"addition","value":1}}]
objectified: [object Object]
resval [object Promise]
2.subbedInstance: 5dbff89209dee20b18091ec3
So despite the "subbedInstance" getting the value, after the Promise resolution, the "substituted" console output (at the test level) shows the unresolved "[object Promise]" for the "appliesTo" value.
So why does the awaited value remain unresolved? even though it actually is resolved?

boolean does not change in function JavaScript

I have the following code:
const ships = (length) => {
isSunk = false
console.log('BEFORE: ' + isSunk)
const shipSize = length
let hits = []
const hitLocation = location => {
hits.push(location);
isSunk = true;
console.log('INSIDE: ' + isSunk)
}
console.log('AFTER: ' + isSunk)
return {
isSunk,
hitLocation,
hits,
shipSize
}
}
const two = ships(2)
two.hitLocation(1)
two.hitLocation(2)
console.log('FINAL: ' + two.isSunk)
console.log('HITS: ' + two.hits)
Is there a reason why isSunk is not saved as true when I call it in the end?
Is it due to the nested functions?
When you set the boolean into the object, it is that value. It is not a reference to the variable. So when you change the variable, the value you saved inside of the object that you returned is not updated.
You can use a function to get the value
const ships = (length) => {
isSunk = false
console.log('BEFORE: ' + isSunk)
const shipSize = length
let hits = []
const hitLocation = location => {
hits.push(location);
isSunk = true;
console.log('INSIDE: ' + isSunk)
}
console.log('AFTER: ' + isSunk)
return {
isSunk: () => isSunk,
hitLocation,
hits,
shipSize
}
}
const two = ships(2)
two.hitLocation(1)
two.hitLocation(2)
console.log('FINAL: ' + two.isSunk())
Other option is to use a class.
class Ship {
hits = [];
constructor(length) {
this.shipSize = length;
}
get isSunk() {
return this.hits.length === this.shipSize;
}
hitLocation (location) {
this.hits.push(location);
console.log('INSIDE: ' + this.isSunk)
}
}
const two = new Ship(2)
two.hitLocation(1)
two.hitLocation(2)
console.log('FINAL: ' + two.isSunk)
The reason this happens is that isSunk is just a local variable and a value in contrast to hits which is also a local variable but an array and thus just a reference not a value.
As you return the object when calling ship() these values and the reference get returned in an object.
Now when you call hitLocation() it uses the local variable hits to add an entry to the array and as the array is just a reference the local variable hits and the hits in the two object have the same reference so they point to the same memory location, thus the update can be seen using the returned object.
On the other hand hitLocation() also modifies the local variable isSunk but as you do not return that and it is not a reference the object stored in variable two is not updated.
The best way to fix this to my mind is using a class instead of a object here. This will be much more concise and clear than returning and/or passing the object you want to perform some action on to a function all the time.

Unhandled rejection SequelizeDatabaseError when passing dynamic query in where clause

I am trying to decompose a user's get request and put it in a variable named query. then pass the var query into the sequelize's findAll method using it's where clause, it seems like Sequelize thinks i am looking for a table CALLED query when in reality i am trying to pass the object. I'm sorry if i can not explain very well, but here is the code and the error:
var info = [];
//link example: localhost:8081/filter/?descripiton=san+francisco&houseType=house&numOfBedroom=3&numOfBathroom=2&houseSize=500&price=1200
exports.filterListings = function(req) {
//create an object literal which we will return, and has a nested object named filteredList inside.
//filteredList contains an array named listings where we will put listings that match our filter inside
let response = {
filteredList: {listings: []},
};
//now we need to see how the user wants us to filter the listings
const query = req.query;
//do some logic where we decompose query
if(query.descripiton != undefined) {
//info = info + 'descripiton: ' + query.descripiton+', ';
info.push('descripiton: ' + query.descripiton+', ');
console.log(info);
}
if(query.houseType != undefined) {
//info = info + 'houseType: ' + query.houseType+', ';
info.push('houseType: ' + query.houseType+', ');
//console.log(info);
}
if(query.numOfBedroom != undefined) {
//info = info + 'numOfBedroom: ' + query.numOfBedroom+', ';
info.push('numOfBedroom: ' + query.numOfBedroom+', ');
}
if(query.numOfBathroom != undefined) {
//info = info + 'numOfBathroom: ' + query.numOfBathroom+', ';
info.push('numOfBathroom: ' + query.numOfBathroom+', ');
}
if(query.houseSize != undefined) {
//info = info + 'houseSize: ' + query.houseSize+', ';
info.push('houseSize: ' + query.houseSize+', ');
}
if(query.price != undefined) {
//info = info + 'price: ' + query.price;
info.push('price: ' + query.price);
}
and then when i try to pass the info variable
listingModel.findAll({
//error because it wont recognize the variable search nor will it recognize info
where: {info}
}).then(listings => {
// so we loop through listings and insert what we have found into the response (which we are going to return)
for(var i = 0; i < listings.length; i++) {
response.filteredList.listings.push(listings[i]);
}; // loop where we insert data into response done
I want it to find all listings based on the dynamic query but i am getting the error:
Unhandled rejection SequelizeDatabaseError: Unknown column 'Listing.info' in 'where clause'
Thank you very much for the potential help!
Let's try to sort through your problems one by one. Sorry for the pun :p
Instead of using multiple if for creating your filtered list. Use for ... in. Then use that array of objects along with Sequelize.Op to create your query.
Example:
const Op = require('sequelize').Op;
const whereClause = [];
const query = req.query;
for(const key in query) {
if(query[key] !== '' && query[key] !== null) {
//object will be pushed to the array like "houseType:big"
whereClause.push({key:query[key]})
}
}
//you now have the where clause
//use it in your query with Op.and
listingModel.findAll({
where: {
[Op.and]: whereClause,
}
});
More info about querying with Sequelize - Operators

How to test a function with different inputs

function addTwo (a, b) {
return a + b;
}
//Leave the function call
addTwo(50, 100);
I'm learning React and I'm trying to create a codecademy type site as a 'learning project', but have run into a JS problem.
Say you have the function above, how do you test it for more than one case? So far I'm testing with:
eval(CODE PULLED IN HERE) === 150 ? alert('Correct!') : alert('Wrong!');
which is obviously going to alert Correct, which is ok for this case. But for other questions (and even this one) I'm going to want more than one test case and that's where I'm stuck.
So, how can I test for multiple test cases, or is there just a whole other way of doing what I'm trying to achieve?
Any help/tips greatly appreciated,
For those who know React here's some code to see a bit of what I currently have :
const CodeEditor = React.createClass({
getInitialState () {
var initialValue = [
"function addTwo () {",
" ",
"}",
"//Leave the function call",
"addTwo(50, 100);"
].join("\n");
return {
kataValue: initialValue
}
},
onChange (newValue) {
this.setState({kataValue: newValue});
},
evalCode () {
var val = this.state.kataValue
eval(val) === 150 ? alert('Correct!') : alert('Wrong!');
},
render () {
return (
<div className="code-editor-wrapper">
<AceEditor
name="editor"
mode="sh"
theme="chaos"
onChange={this.onChange}
value={this.state.kataValue}
editorProps={{$blockScrolling: true}}
/>
<button onClick={this.evalCode} className="spec-btn submit-code-btn">Evaluate</button>
</div>
)
}
})
Don't include the function call in the user's code. Only require the function to be named in a certain way. Instead of directly evaling the user's code, embed into a function that returns the user's function:
function getUserFunction(code, functionName) {
var userCode = new Function(code + '; return ' + functionName + ';');
return userCode();
}
After calling getUserFunction you have a reference to the function the user wrote and you can execute it as often as you want. How you structure your test cases and how much feedback you want to give to the user is up to you.
Here is small example:
var userFn = getUserFunction(this.state.kataValue, 'addTwo');
var testCases = [
[[50, 100], 150],
[[1, 2], 3],
];
var passes = testCases.every(
([input, output]) => userFn(...input) === output
);
if (passes) {
// all test cases pass
}
You can iterate over a bunch of inputs like so:
function addTwo(a, b) {
return a + b
}
for (var i = 0, j; i < 100; i++) {
for (j = 0; j < 100; j++) {
if (addTwo(i, j) !== i + j) console.error('Wrong output for inputs ' + i + ' and ' + j)
}
}

Categories

Resources