Cannot get variable from sql query in Node - mysql

Sorry, I read about handling async functions in order to get variable names from them but I am not sure what I am doing wrong and how to handle it.
for(let j = 0; j < ga.length; j++) {
var sql = "SELECT * FROM matches WHERE clh = '"+ga[j]+"'"
const dbq = db.query(sql, function(err, result) {
if (err) console.log(err);
var gs1 = 0;
var gs2 = 0;
var pts1 = 0;
var w1 = 0;
var d1 = 0;
var l1 = 0;
for (let i = 0; i < result.length; i++) {
gs1 += result[i].gsh;
gs2 += result[i].gsa;
const r = mgs1(result[i].gsh, result[i].gsa);
if (r == 3) w1 += 1;
if (r == 1) d1 += 1;
if (r == 0) l1 += 1;
var gd1 = gs1 - gs2;
var r1 = [result[i].clh, result.length, w1, d1, l1, gs1, gs2, gd1 ];
}
gs4.push(r1);
if (gs4.length == 6) {
return gs4;
}
})
}
}
This function returns the array that I want but I am not sure how to access it outside the db.query block. I read posts about handling variables from async functions but I just can't seem to do it in this example. Thanks a lot in advance

I guess you have defined const gs4 = [] somewhere in code you did not show us. That's part of the answer to your question: it will be populated after your callback from db.query() completes.
The rest of the answer: it is not populated until after the callback completes. Also, the return from inside your callback is meaningless; it just returns to db.query() .
Also, db.query() returns to its caller instantly, long before it calls its callback. So your loop tries to run multiple queries concurrently. I guess the result in gs4 will accumulate the results from all the queries.
With respect, I believe a quick jump up the learning curve for Promises or async / await lies in your near future.
This may help : node.js mysql query in a for loop

If you would like to query the database the correct way, you should use the embedded functions that comes with database driver. For string interpolation and returning data for your functions.
exports.lookupLogin = (req, res, next) => {
let sql = 'SELECT e.employee_id, e.login, e.password FROM employee e WHERE e.login=?';
postgres.client.query(sql, [req.body.login], (error, result, fields) => {
if (err) {
return res.status(500).json({ errors: ['Could not do login'] });
}
res.status(200).json(result.rows);
});
};
For more information you can check the mysql documentation to use with nodejs.

Related

for loop not letting me loop entire request.post of a json object! node.js [duplicate]

var funcs = [];
// let's create 3 functions
for (var i = 0; i < 3; i++) {
// and store them in funcs
funcs[i] = function() {
// each should log its value.
console.log("My value:", i);
};
}
for (var j = 0; j < 3; j++) {
// and now let's run each one to see
funcs[j]();
}
It outputs this:
My value: 3
My value: 3
My value: 3
Whereas I'd like it to output:
My value: 0
My value: 1
My value: 2
The same problem occurs when the delay in running the function is caused by using event listeners:
var buttons = document.getElementsByTagName("button");
// let's create 3 functions
for (var i = 0; i < buttons.length; i++) {
// as event listeners
buttons[i].addEventListener("click", function() {
// each should log its value.
console.log("My value:", i);
});
}
<button>0</button>
<br />
<button>1</button>
<br />
<button>2</button>
… or asynchronous code, e.g. using Promises:
// Some async wait function
const wait = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms));
for (var i = 0; i < 3; i++) {
// Log `i` as soon as each promise resolves.
wait(i * 100).then(() => console.log(i));
}
It is also apparent in for in and for of loops:
const arr = [1,2,3];
const fns = [];
for (var i in arr){
fns.push(() => console.log("index:", i));
}
for (var v of arr){
fns.push(() => console.log("value:", v));
}
for (const n of arr) {
var obj = { number: n }; // or new MyLibObject({ ... })
fns.push(() => console.log("n:", n, "|", "obj:", JSON.stringify(obj)));
}
for(var f of fns){
f();
}
What’s the solution to this basic problem?
Well, the problem is that the variable i, within each of your anonymous functions, is bound to the same variable outside of the function.
ES6 solution: let
ECMAScript 6 (ES6) introduces new let and const keywords that are scoped differently than var-based variables. For example, in a loop with a let-based index, each iteration through the loop will have a new variable i with loop scope, so your code would work as you expect. There are many resources, but I'd recommend 2ality's block-scoping post as a great source of information.
for (let i = 0; i < 3; i++) {
funcs[i] = function() {
console.log("My value: " + i);
};
}
Beware, though, that IE9-IE11 and Edge prior to Edge 14 support let but get the above wrong (they don't create a new i each time, so all the functions above would log 3 like they would if we used var). Edge 14 finally gets it right.
ES5.1 solution: forEach
With the relatively widespread availability of the Array.prototype.forEach function (in 2015), it's worth noting that in those situations involving iteration primarily over an array of values, .forEach() provides a clean, natural way to get a distinct closure for every iteration. That is, assuming you've got some sort of array containing values (DOM references, objects, whatever), and the problem arises of setting up callbacks specific to each element, you can do this:
var someArray = [ /* whatever */ ];
// ...
someArray.forEach(function(arrayElement) {
// ... code code code for this one element
someAsynchronousFunction(arrayElement, function() {
arrayElement.doSomething();
});
});
The idea is that each invocation of the callback function used with the .forEach loop will be its own closure. The parameter passed in to that handler is the array element specific to that particular step of the iteration. If it's used in an asynchronous callback, it won't collide with any of the other callbacks established at other steps of the iteration.
If you happen to be working in jQuery, the $.each() function gives you a similar capability.
Classic solution: Closures
What you want to do is bind the variable within each function to a separate, unchanging value outside of the function:
var funcs = [];
function createfunc(i) {
return function() {
console.log("My value: " + i);
};
}
for (var i = 0; i < 3; i++) {
funcs[i] = createfunc(i);
}
for (var j = 0; j < 3; j++) {
// and now let's run each one to see
funcs[j]();
}
Since there is no block scope in JavaScript - only function scope - by wrapping the function creation in a new function, you ensure that the value of "i" remains as you intended.
Try:
var funcs = [];
for (var i = 0; i < 3; i++) {
funcs[i] = (function(index) {
return function() {
console.log("My value: " + index);
};
}(i));
}
for (var j = 0; j < 3; j++) {
funcs[j]();
}
Edit (2014):
Personally I think #Aust's more recent answer about using .bind is the best way to do this kind of thing now. There's also lo-dash/underscore's _.partial when you don't need or want to mess with bind's thisArg.
Another way that hasn't been mentioned yet is the use of Function.prototype.bind
var funcs = {};
for (var i = 0; i < 3; i++) {
funcs[i] = function(x) {
console.log('My value: ' + x);
}.bind(this, i);
}
for (var j = 0; j < 3; j++) {
funcs[j]();
}
UPDATE
As pointed out by #squint and #mekdev, you get better performance by creating the function outside the loop first and then binding the results within the loop.
function log(x) {
console.log('My value: ' + x);
}
var funcs = [];
for (var i = 0; i < 3; i++) {
funcs[i] = log.bind(this, i);
}
for (var j = 0; j < 3; j++) {
funcs[j]();
}
Using an Immediately-Invoked Function Expression, the simplest and most readable way to enclose an index variable:
for (var i = 0; i < 3; i++) {
(function(index) {
console.log('iterator: ' + index);
//now you can also loop an ajax call here
//without losing track of the iterator value: $.ajax({});
})(i);
}
This sends the iterator i into the anonymous function of which we define as index. This creates a closure, where the variable i gets saved for later use in any asynchronous functionality within the IIFE.
Bit late to the party, but I was exploring this issue today and noticed that many of the answers don't completely address how Javascript treats scopes, which is essentially what this boils down to.
So as many others mentioned, the problem is that the inner function is referencing the same i variable. So why don't we just create a new local variable each iteration, and have the inner function reference that instead?
//overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '<p>' + msg + '</p>';};
var funcs = {};
for (var i = 0; i < 3; i++) {
var ilocal = i; //create a new local variable
funcs[i] = function() {
console.log("My value: " + ilocal); //each should reference its own local variable
};
}
for (var j = 0; j < 3; j++) {
funcs[j]();
}
Just like before, where each inner function outputted the last value assigned to i, now each inner function just outputs the last value assigned to ilocal. But shouldn't each iteration have it's own ilocal?
Turns out, that's the issue. Each iteration is sharing the same scope, so every iteration after the first is just overwriting ilocal. From MDN:
Important: JavaScript does not have block scope. Variables introduced with a block are scoped to the containing function or script, and the effects of setting them persist beyond the block itself. In other words, block statements do not introduce a scope. Although "standalone" blocks are valid syntax, you do not want to use standalone blocks in JavaScript, because they don't do what you think they do, if you think they do anything like such blocks in C or Java.
Reiterated for emphasis:
JavaScript does not have block scope. Variables introduced with a block are scoped to the containing function or script
We can see this by checking ilocal before we declare it in each iteration:
//overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '<p>' + msg + '</p>';};
var funcs = {};
for (var i = 0; i < 3; i++) {
console.log(ilocal);
var ilocal = i;
}
This is exactly why this bug is so tricky. Even though you are redeclaring a variable, Javascript won't throw an error, and JSLint won't even throw a warning. This is also why the best way to solve this is to take advantage of closures, which is essentially the idea that in Javascript, inner functions have access to outer variables because inner scopes "enclose" outer scopes.
This also means that inner functions "hold onto" outer variables and keep them alive, even if the outer function returns. To utilize this, we create and call a wrapper function purely to make a new scope, declare ilocal in the new scope, and return an inner function that uses ilocal (more explanation below):
//overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '<p>' + msg + '</p>';};
var funcs = {};
for (var i = 0; i < 3; i++) {
funcs[i] = (function() { //create a new scope using a wrapper function
var ilocal = i; //capture i into a local var
return function() { //return the inner function
console.log("My value: " + ilocal);
};
})(); //remember to run the wrapper function
}
for (var j = 0; j < 3; j++) {
funcs[j]();
}
Creating the inner function inside a wrapper function gives the inner function a private environment that only it can access, a "closure". Thus, every time we call the wrapper function we create a new inner function with it's own separate environment, ensuring that the ilocal variables don't collide and overwrite each other. A few minor optimizations gives the final answer that many other SO users gave:
//overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '<p>' + msg + '</p>';};
var funcs = {};
for (var i = 0; i < 3; i++) {
funcs[i] = wrapper(i);
}
for (var j = 0; j < 3; j++) {
funcs[j]();
}
//creates a separate environment for the inner function
function wrapper(ilocal) {
return function() { //return the inner function
console.log("My value: " + ilocal);
};
}
Update
With ES6 now mainstream, we can now use the new let keyword to create block-scoped variables:
//overwrite console.log() so you can see the console output
console.log = function(msg) {document.body.innerHTML += '<p>' + msg + '</p>';};
var funcs = {};
for (let i = 0; i < 3; i++) { // use "let" to declare "i"
funcs[i] = function() {
console.log("My value: " + i); //each should reference its own local variable
};
}
for (var j = 0; j < 3; j++) { // we can use "var" here without issue
funcs[j]();
}
Look how easy it is now! For more information see this answer, which my info is based off of.
With ES6 now widely supported, the best answer to this question has changed. ES6 provides the let and const keywords for this exact circumstance. Instead of messing around with closures, we can just use let to set a loop scope variable like this:
var funcs = [];
for (let i = 0; i < 3; i++) {
funcs[i] = function() {
console.log("My value: " + i);
};
}
val will then point to an object that is specific to that particular turn of the loop, and will return the correct value without the additional closure notation. This obviously significantly simplifies this problem.
const is similar to let with the additional restriction that the variable name can't be rebound to a new reference after initial assignment.
Browser support is now here for those targeting the latest versions of browsers. const/let are currently supported in the latest Firefox, Safari, Edge and Chrome. It also is supported in Node, and you can use it anywhere by taking advantage of build tools like Babel. You can see a working example here: http://jsfiddle.net/ben336/rbU4t/2/
Docs here:
const
let
Beware, though, that IE9-IE11 and Edge prior to Edge 14 support let but get the above wrong (they don't create a new i each time, so all the functions above would log 3 like they would if we used var). Edge 14 finally gets it right.
Another way of saying it is that the i in your function is bound at the time of executing the function, not the time of creating the function.
When you create the closure, i is a reference to the variable defined in the outside scope, not a copy of it as it was when you created the closure. It will be evaluated at the time of execution.
Most of the other answers provide ways to work around by creating another variable that won't change the value for you.
Just thought I'd add an explanation for clarity. For a solution, personally, I'd go with Harto's since it is the most self-explanatory way of doing it from the answers here. Any of the code posted will work, but I'd opt for a closure factory over having to write a pile of comments to explain why I'm declaring a new variable(Freddy and 1800's) or have weird embedded closure syntax(apphacker).
What you need to understand is the scope of the variables in javascript is based on the function. This is an important difference than say c# where you have block scope, and just copying the variable to one inside the for will work.
Wrapping it in a function that evaluates returning the function like apphacker's answer will do the trick, as the variable now has the function scope.
There is also a let keyword instead of var, that would allow using the block scope rule. In that case defining a variable inside the for would do the trick. That said, the let keyword isn't a practical solution because of compatibility.
var funcs = {};
for (var i = 0; i < 3; i++) {
let index = i; //add this
funcs[i] = function() {
console.log("My value: " + index); //change to the copy
};
}
for (var j = 0; j < 3; j++) {
funcs[j]();
}
Here's another variation on the technique, similar to Bjorn's (apphacker), which lets you assign the variable value inside the function rather than passing it as a parameter, which might be clearer sometimes:
var funcs = [];
for (var i = 0; i < 3; i++) {
funcs[i] = (function() {
var index = i;
return function() {
console.log("My value: " + index);
}
})();
}
Note that whatever technique you use, the index variable becomes a sort of static variable, bound to the returned copy of the inner function. I.e., changes to its value are preserved between calls. It can be very handy.
This describes the common mistake with using closures in JavaScript.
A function defines a new environment
Consider:
function makeCounter()
{
var obj = {counter: 0};
return {
inc: function(){obj.counter ++;},
get: function(){return obj.counter;}
};
}
counter1 = makeCounter();
counter2 = makeCounter();
counter1.inc();
alert(counter1.get()); // returns 1
alert(counter2.get()); // returns 0
For each time makeCounter is invoked, {counter: 0} results in a new object being created. Also, a new copy of obj
is created as well to reference the new object. Thus, counter1 and counter2 are independent of each other.
Closures in loops
Using a closure in a loop is tricky.
Consider:
var counters = [];
function makeCounters(num)
{
for (var i = 0; i < num; i++)
{
var obj = {counter: 0};
counters[i] = {
inc: function(){obj.counter++;},
get: function(){return obj.counter;}
};
}
}
makeCounters(2);
counters[0].inc();
alert(counters[0].get()); // returns 1
alert(counters[1].get()); // returns 1
Notice that counters[0] and counters[1] are not independent. In fact, they operate on the same obj!
This is because there is only one copy of obj shared across all iterations of the loop, perhaps for performance reasons.
Even though {counter: 0} creates a new object in each iteration, the same copy of obj will just get updated with a
reference to the newest object.
Solution is to use another helper function:
function makeHelper(obj)
{
return {
inc: function(){obj.counter++;},
get: function(){return obj.counter;}
};
}
function makeCounters(num)
{
for (var i = 0; i < num; i++)
{
var obj = {counter: 0};
counters[i] = makeHelper(obj);
}
}
This works because local variables in the function scope directly, as well as function argument variables, are allocated
new copies upon entry.
The most simple solution would be,
Instead of using:
var funcs = [];
for(var i =0; i<3; i++){
funcs[i] = function(){
alert(i);
}
}
for(var j =0; j<3; j++){
funcs[j]();
}
which alerts "2", for 3 times. This is because anonymous functions created in for loop, shares same closure, and in that closure, the value of i is the same. Use this to prevent shared closure:
var funcs = [];
for(var new_i =0; new_i<3; new_i++){
(function(i){
funcs[i] = function(){
alert(i);
}
})(new_i);
}
for(var j =0; j<3; j++){
funcs[j]();
}
The idea behind this is, encapsulating the entire body of the for loop with an IIFE (Immediately-Invoked Function Expression) and passing new_i as a parameter and capturing it as i. Since the anonymous function is executed immediately, the i value is different for each function defined inside the anonymous function.
This solution seems to fit any such problem since it will require minimal changes to the original code suffering from this issue. In fact, this is by design, it should not be an issue at all!
Here's a simple solution that uses forEach (works back to IE9):
var funcs = [];
[0,1,2].forEach(function(i) { // let's create 3 functions
funcs[i] = function() { // and store them in funcs
console.log("My value: " + i); // each should log its value.
};
})
for (var j = 0; j < 3; j++) {
funcs[j](); // and now let's run each one to see
}
Prints:
My value: 0
My value: 1
My value: 2
try this shorter one
no array
no extra for loop
for (var i = 0; i < 3; i++) {
createfunc(i)();
}
function createfunc(i) {
return function(){console.log("My value: " + i);};
}
http://jsfiddle.net/7P6EN/
The main issue with the code shown by the OP is that i is never read until the second loop. To demonstrate, imagine seeing an error inside of the code
funcs[i] = function() { // and store them in funcs
throw new Error("test");
console.log("My value: " + i); // each should log its value.
};
The error actually does not occur until funcs[someIndex] is executed (). Using this same logic, it should be apparent that the value of i is also not collected until this point either. Once the original loop finishes, i++ brings i to the value of 3 which results in the condition i < 3 failing and the loop ending. At this point, i is 3 and so when funcs[someIndex]() is used, and i is evaluated, it is 3 - every time.
To get past this, you must evaluate i as it is encountered. Note that this has already happened in the form of funcs[i] (where there are 3 unique indexes). There are several ways to capture this value. One is to pass it in as a parameter to a function which is shown in several ways already here.
Another option is to construct a function object which will be able to close over the variable. That can be accomplished thusly
jsFiddle Demo
funcs[i] = new function() {
var closedVariable = i;
return function(){
console.log("My value: " + closedVariable);
};
};
JavaScript functions "close over" the scope they have access to upon declaration, and retain access to that scope even as variables in that scope change.
var funcs = []
for (var i = 0; i < 3; i += 1) {
funcs[i] = function () {
console.log(i)
}
}
for (var k = 0; k < 3; k += 1) {
funcs[k]()
}
Each function in the array above closes over the global scope (global, simply because that happens to be the scope they're declared in).
Later those functions are invoked logging the most current value of i in the global scope. That's the magic, and frustration, of closure.
"JavaScript Functions close over the scope they are declared in, and retain access to that scope even as variable values inside of that scope change."
Using let instead of var solves this by creating a new scope each time the for loop runs, creating a separated scope for each function to close over. Various other techniques do the same thing with extra functions.
var funcs = []
for (let i = 0; i < 3; i += 1) {
funcs[i] = function () {
console.log(i)
}
}
for (var k = 0; k < 3; k += 1) {
funcs[k]()
}
(let makes variables block scoped. Blocks are denoted by curly braces, but in the case of the for loop the initialization variable, i in our case, is considered to be declared in the braces.)
After reading through various solutions, I'd like to add that the reason those solutions work is to rely on the concept of scope chain. It's the way JavaScript resolve a variable during execution.
Each function definition forms a scope consisting of all the local
variables declared by var and its arguments.
If we have inner function defined inside another (outer) function, this
forms a chain, and will be used during execution
When a function gets executed, the runtime evaluates variables by searching the scope chain. If a variable can be found in a certain point of the chain it will stop searching and use it, otherwise it continues until the global scope reached which belongs to window.
In the initial code:
funcs = {};
for (var i = 0; i < 3; i++) {
funcs[i] = function inner() { // function inner's scope contains nothing
console.log("My value: " + i);
};
}
console.log(window.i) // test value 'i', print 3
When funcs gets executed, the scope chain will be function inner -> global. Since the variable i cannot be found in function inner (neither declared using var nor passed as arguments), it continues to search, until the value of i is eventually found in the global scope which is window.i.
By wrapping it in an outer function either explicitly define a helper function like harto did or use an anonymous function like Bjorn did:
funcs = {};
function outer(i) { // function outer's scope contains 'i'
return function inner() { // function inner, closure created
console.log("My value: " + i);
};
}
for (var i = 0; i < 3; i++) {
funcs[i] = outer(i);
}
console.log(window.i) // print 3 still
When funcs gets executed, now the scope chain will be function inner -> function outer. This time i can be found in the outer function's scope which is executed 3 times in the for loop, each time has value i bound correctly. It won't use the value of window.i when inner executed.
More detail can be found here
It includes the common mistake in creating closure in the loop as what we have here, as well as why we need closure and the performance consideration.
With new features of ES6 block level scoping is managed:
var funcs = [];
for (let i = 0; i < 3; i++) { // let's create 3 functions
funcs[i] = function() { // and store them in funcs
console.log("My value: " + i); // each should log its value.
};
}
for (let j = 0; j < 3; j++) {
funcs[j](); // and now let's run each one to see
}
The code in OP's question is replaced with let instead of var.
We will check , what actually happens when you declare var and let
one by one.
Case1 : using var
<script>
var funcs = [];
for (var i = 0; i < 3; i++) {
funcs[i] = function () {
debugger;
console.log("My value: " + i);
};
}
console.log(funcs);
</script>
Now open your chrome console window by pressing F12 and refresh the page.
Expend every 3 functions inside the array.You will see an property called [[Scopes]].Expand that one. You will see one
array object called "Global",expand that one. You will find a property 'i' declared into the object which having value 3.
Conclusion:
When you declare a variable using 'var' outside a function ,it becomes global variable(you can check by typing i or
window.i in console window.It will return 3).
The anonymous function you declared will not call and check the value inside the function unless you invoke the
functions.
When you invoke the function , console.log("My value: " + i) takes the value from its Global object and display the
result.
CASE2 : using let
Now replace the 'var' with 'let'
<script>
var funcs = [];
for (let i = 0; i < 3; i++) {
funcs[i] = function () {
debugger;
console.log("My value: " + i);
};
}
console.log(funcs);
</script>
Do the same thing, Go to the scopes . Now you will see two objects "Block" and "Global". Now expand Block object , you
will see 'i' is defined there , and the strange thing is that , for every functions , the value if i is different (0 , 1, 2).
Conclusion:
When you declare variable using 'let' even outside the function but inside the loop , this variable will not be a Global
variable , it will become a Block level variable which is only available for the same function only.That is the reason , we
are getting value of i different for each function when we invoke the functions.
For more detail about how closer works , please go through the awesome video tutorial https://youtu.be/71AtaJpJHw0
I'm surprised no one yet has suggested using the forEach function to better avoid (re)using local variables. In fact, I'm not using for(var i ...) at all anymore for this reason.
[0,2,3].forEach(function(i){ console.log('My value:', i); });
// My value: 0
// My value: 2
// My value: 3
// edited to use forEach instead of map.
The reason your original example did not work is that all the closures you created in the loop referenced the same frame. In effect, having 3 methods on one object with only a single i variable. They all printed out the same value.
This question really shows the history of JavaScript! Now we can avoid block scoping with arrow functions and handle loops directly from DOM nodes using Object methods.
const funcs = [1, 2, 3].map(i => () => console.log(i));
funcs.map(fn => fn())
const buttons = document.getElementsByTagName("button");
Object
.keys(buttons)
.map(i => buttons[i].addEventListener('click', () => console.log(i)));
<button>0</button><br>
<button>1</button><br>
<button>2</button>
First of all, understand what's wrong with this code:
var funcs = [];
for (var i = 0; i < 3; i++) { // let's create 3 functions
funcs[i] = function() { // and store them in funcs
console.log("My value: " + i); // each should log its value.
};
}
for (var j = 0; j < 3; j++) {
funcs[j](); // and now let's run each one to see
}
Here when the funcs[] array is being initialized, i is being incremented, the funcs array is initialized and the size of func array becomes 3, so i = 3,.
Now when the funcs[j]() is called, it is again using the variable i, which has already been incremented to 3.
Now to solve this, we have many options. Below are two of them:
We can initialize i with let or initialize a new variable index with let and make it equal to i. So when the call is being made, index will be used and its scope will end after initialization. And for calling, index will be initialized again:
var funcs = [];
for (var i = 0; i < 3; i++) {
let index = i;
funcs[i] = function() {
console.log("My value: " + index);
};
}
for (var j = 0; j < 3; j++) {
funcs[j]();
}
Other Option can be to introduce a tempFunc which returns the actual function:
var funcs = [];
function tempFunc(i){
return function(){
console.log("My value: " + i);
};
}
for (var i = 0; i < 3; i++) {
funcs[i] = tempFunc(i);
}
for (var j = 0; j < 3; j++) {
funcs[j]();
}
Use closure structure, this would reduce your extra for loop. You can do it in a single for loop:
var funcs = [];
for (var i = 0; i < 3; i++) {
(funcs[i] = function() {
console.log("My value: " + i);
})(i);
}
Till ES5, This problem can only be solved using closure.
But now in ES6, we have block level scope variables. Changing var to let in first for loop will solve the problem.
var funcs = [];
for (let i = 0; i < 3; i++) { // let's create 3 functions
funcs[i] = function() { // and store them in funcs
console.log("My value: " + i); // each should log its value.
};
}
for (var j = 0; j < 3; j++) {
funcs[j](); // and now let's run each one to see
}
If you're having this sort of problem with a while loop, rather than a for loop, for example:
var i = 0;
while (i < 5) {
setTimeout(function() {
console.log(i);
}, i * 1000);
i++;
}
The technique to close over the current value is a bit different. Declare a block-scoped variable with const inside the while block, and assign the current i to it. Then, wherever the variable is being used asynchronously, replace i with the new block-scoped variable:
var i = 0;
while (i < 5) {
const thisIterationI = i;
setTimeout(function() {
console.log(thisIterationI);
}, i * 1000);
i++;
}
For older browsers that don't support block-scoped variables, you can use an IIFE called with i:
var i = 0;
while (i < 5) {
(function(innerI) {
setTimeout(function() {
console.log(innerI);
}, innerI * 1000);
})(i);
i++;
}
If the asynchronous action to be invoked happens to be setTimeout like the above, you can also call setTimeout with a third parameter to indicate the argument to call the passed function with:
var i = 0;
while (i < 5) {
setTimeout(
(thisIterationI) => { // Callback
console.log(thisIterationI);
},
i * 1000, // Delay
i // Gets passed to the callback; becomes thisIterationI
);
i++;
}
You could use a declarative module for lists of data such as query-js(*). In these situations I personally find a declarative approach less surprising
var funcs = Query.range(0,3).each(function(i){
return function() {
console.log("My value: " + i);
};
});
You could then use your second loop and get the expected result or you could do
funcs.iterate(function(f){ f(); });
(*) I'm the author of query-js and therefor biased towards using it, so don't take my words as a recommendation for said library only for the declarative approach :)
I prefer to use forEach function, which has its own closure with creating a pseudo range:
var funcs = [];
new Array(3).fill(0).forEach(function (_, i) { // creating a range
funcs[i] = function() {
// now i is safely incapsulated
console.log("My value: " + i);
};
});
for (var j = 0; j < 3; j++) {
funcs[j](); // 0, 1, 2
}
That looks uglier than ranges in other languages, but IMHO less monstrous than other solutions.
And yet another solution: instead of creating another loop, just bind the this to the return function.
var funcs = [];
function createFunc(i) {
return function() {
console.log('My value: ' + i); //log value of i.
}.call(this);
}
for (var i = 1; i <= 5; i++) { //5 functions
funcs[i] = createFunc(i); // call createFunc() i=5 times
}
By binding this, solves the problem as well.
Your code doesn't work, because what it does is:
Create variable `funcs` and assign it an empty array;
Loop from 0 up until it is less than 3 and assign it to variable `i`;
Push to variable `funcs` next function:
// Only push (save), but don't execute
**Write to console current value of variable `i`;**
// First loop has ended, i = 3;
Loop from 0 up until it is less than 3 and assign it to variable `j`;
Call `j`-th function from variable `funcs`:
**Write to console current value of variable `i`;**
// Ask yourself NOW! What is the value of i?
Now the question is, what is the value of variable i when the function is called? Because the first loop is created with the condition of i < 3, it stops immediately when the condition is false, so it is i = 3.
You need to understand that, in time when your functions are created, none of their code is executed, it is only saved for later. And so when they are called later, the interpreter executes them and asks: "What is the current value of i?"
So, your goal is to first save the value of i to function and only after that save the function to funcs. This could be done for example this way:
var funcs = [];
for (var i = 0; i < 3; i++) { // let's create 3 functions
funcs[i] = function(x) { // and store them in funcs
console.log("My value: " + x); // each should log its value.
}.bind(null, i);
}
for (var j = 0; j < 3; j++) {
funcs[j](); // and now let's run each one to see
}
This way, each function will have it's own variable x and we set this x to the value of i in each iteration.
This is only one of the multiple ways to solve this problem.
var funcs = [];
for (var i = 0; i < 3; i++) { // let's create 3 functions
funcs[i] = function(param) { // and store them in funcs
console.log("My value: " + param); // each should log its value.
};
}
for (var j = 0; j < 3; j++) {
funcs[j](j); // and now let's run each one to see with j
}

How to determine completion?

I am creating currency rates website backend in node js with MongoDB and MySQL,
At first I am storing data into MongoDB from API and afterwards, for saving RAM and CPU I have decided to create and store analytical data into MySQL.
Please look at following code,
update24HRateArr: () => {
var da = [];
db.query('TRUNCATE TABLE `rate24h`', (xerr, xres) => {
if (xerr) console.log(xerr.message);
});
mdb.currency((currList) => {
if (currList && currList.length > 0) {
currList.length = 50;
for (var c = 0; c < currList.length; c++) {
mdb.rateArr(currList[c], '24h', (data) => {
if (data && data.length > 0) {
for (var i = 0; i < data.length; i++) {
var tmp = [];
tmp.push(data[i].id);//1->id
tmp.push(i);//2->number
tmp.push(data[i].time);//3->time value
tmp.push(data[i].price_usd);//4->price usd
tmp.push(data[i].price_btc);//5->price btc
tmp.push(data[i].price_inr);//6->price inr
tmp.push(fn.time.unix());//7->DB update time
da.push(tmp);
}
//main area for done call
/*
if (da.length == 1200) {
db.query('INSERT INTO `rate24h` VALUES ?', [da], (err, datax) => {
if (err) console.log(err);
else {
console.log(`${fn.time.timeStamp()} Data(${datax.affectedRows}) Inserted for Rate24H`);
}
});
console.log(da);
}*/
console.log(`inside i ${da.length}`);
}
console.log(`inside iRateArr ${da.length}`);
});
//console.log(`inside c ${da.length}`); <- always 0 no way
}
}
else {
console.log('Currency Loading failed');
}
});
},
Now, I know that length of da var is gonna be 1200 in this case because 50 currencies and 24 hours but in some cases it's flexible,
I can't exactly determine when this da var updating will be completed via for loops so I can execute insert query to mysql
that if(da.length ===1200) is not enough I need exact point that I can execute INSERT query.
Thank you

How to save the result of MySql query in variable using node-mysql [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 1 year ago.
im trying to save the result of MySql query in variable using node-mysql model and node.js so i have this code:
connection.query("select * from ROOMS", function(err, rows){
if(err) {
throw err;
} else {
console.log(rows);
}
});
and the result is :
[ { idRooms: 1, Room_Name: 'dd' },
{ idRooms: 2, Room_Name: 'sad' } ]
so i need to store this results in variable so i try like this:
var someVar = connection.query("select * from ROOMS", function(err, rows){
if(err) {
throw err;
} else {
return rows;
}
});
console.log(someVar);
but is not working thanks for any help in advance.
Well #Fadi, connection.query is async, which mean when your call your console.log(someVar), someVar has not been set yet.
What you could do:
var someVar = [];
connection.query("select * from ROOMS", function(err, rows){
if(err) {
throw err;
} else {
setValue(rows);
}
});
function setValue(value) {
someVar = value;
console.log(someVar);
}
You can't do that because network i/o is asynchronous and non-blocking in node.js. So any logic that comes afterwards that must execute only after the query has finished, you must place inside the query's callback. If you have many nested asynchronous operations you may look into using a module such as async to help better organize your asynchronous tasks.
As a complement to already given answers.
var **someVar** = connection.query( *sqlQuery*, *callback function( err , row , fields){}* )
console.log(**someVar**);
This construction will return in someVar information of this connection and his SQL query . It will not return values ​​from the query .
Values ​​from the query are located in the callback function ( err , row , fields)
Here is your answer if you want to assign a variable to res.render
//before define the values
var tum_render = [];
tum_render.title = "Turan";
tum_render.description = "Turan'ın websitesi";
//left the queries seperatly
var rastgeleQuery = "SELECT baslik,hit FROM icerik ORDER BY RAND() LIMIT 1";
var son5Query = "SELECT baslik,hit FROM icerik LIMIT 5";
var query_arr = [rastgeleQuery, son5Query];
var query_name = ['rastgele', 'son5'];
//and the functions are
//query for db
function runQuery(query_arr,sira){
connection.query(query_arr[sira], function(err, rows, fields) {
if (err) throw err;
var obj = [];
obj[query_name[sira]] = rows;
sonuclar.push(obj);
if (query_arr.length <= sira+1){
sonuc();
}else{
runQuery(query_arr, sira+1);
}
});
}
//the function joins some functions http://stackoverflow.com/questions/2454295/javascript-concatenate-properties-from-multiple-objects-associative-array
function collect() {
var ret = {};
var len = arguments.length;
for (var i=0; i<len; i++) {
for (p in arguments[i]) {
if (arguments[i].hasOwnProperty(p)) {
ret[p] = arguments[i][p];
}
}
}
return ret;
}
//runQuery callback
function sonuc(){
for(var x = 0; x<=sonuclar.length-1; x++){
tum_render = collect(tum_render,sonuclar[x]);
}
console.log(tum_render);
res.render('index', tum_render);
}

How to pass parameters to mysql query callback in nodejs

I'm trying to figure out the correct way of passing custom data to a query call to be made available in the callback.
I'm using MySQL library in nodejs (all latest versions).
I have a call to connection.query(sql, function(err, result) {...});
I couldn't find a way to 1) pass custom data/parameter to the call so that 2) it can be made available when the callback is invoked.
So what is the proper way of doing so?
I have the following (pseudo-code):
...
for (ix in SomeJSONArray) {
sql = "SELECT (1) FROM someTable WHERE someColumn = " + SomeJSONArray[ix].id;
connection.query(sql, function (err, result) {
...
var y = SomeJSONArray[ix].id;
};
}
From the code above, I need to be able to pass the current value of "ix" used in the query to the callback itself.
How do I do that?
If you are using node-mysql, do it like the docs say:
connection.query(
'SELECT * FROM table WHERE id=? LIMIT ?, 5',[ user_id, start ],
function (err, results) {
}
);
The docs also have code for proper escaping of strings, but using the array in the query call automatically does the escaping for you.
https://github.com/felixge/node-mysql
To answer the initial question with a complete answer/example to illustrate, wrap the callback with an anonymous function which immediately creates a scope containing a "snapshot" if you will of the data passed in.
var ix=1;
connection.query('SELECT 1',
(function(ix){
return function(err, rows, fields) {
console.log("ix="+ix);
console.log(rows);
};
})(ix));
For those new to this concept as I was 20 minutes ago, the last })(ix)); is the outer var ix=1 value which is passed into (function(ix){. This could be renamed (function(abc){ if you changed the console.log("ix="+abc);
fwiw (Thanks Chris for the link which filled in the blanks to arrive at a solution)
While it is OK to pass variables or objects to a mysql query callback function using the tactic described earlier -- wrapping the callback function in an anonymous function -- I think it is largely unnecessary, and I'll explain why with an example:
// This actually works as expected!
function run_query (sql, y) {
var y1 = 1;
connection.query (sql, function (error, rows, fields) {
if (! error)
{
var r = rows[0];
console.log ("r = " + r[1]);
console.log ("x = " + x);
console.log ("y = " + y);
console.log ("y1= " + y);
console.log ("");
}
else
{
console.log ("error = " + error);
}
});
};
var x = 5;
console.log ("step 1: x = " + x);
run_query ("SELECT 1", x);
x = x + 1;
console.log ("step 2: x = " + x);
run_query ("SELECT 1", x);
x = x + 1;
console.log ("step 3: x = " + x);
Produces the following output:
step 1: x = 5
step 2: x = 6
step 3: x = 7
r = 1
x = 7
y = 5
y1= 5
r = 1
x = 7
y = 6
y1= 6
The fear is that the second call to run_query() will overwrite the variable y and/or y1 before the first call to run_query() has a chance to invoke its callback function. However, the variables in each instance of the called run_query() function are actually isolated from each other, saving the day.
MySQL con.query has overloaded function. Inside of callback you use global variable or any variable that is passed into your function parameter. For example:
Example 1: it takes sql string and callback function
var adr = 'Mountain 21';
var sql = 'SELECT * FROM customers;
con.query(sql, function (err, result) {
if (err) throw err;
console.log(adr);
});
Example 2: it takes sql string, parameter and callback function
var adr = 'Mountain 21';
var sql = 'SELECT * FROM customers WHERE address = ?';
con.query(sql, [adr], function (err, result) {
if (err) throw err;
console.log(adr);
});

How can I do this asyn feature in nodejs

I have a code to do some calculation.
How can I write this code in an asyn way?
When query the database, seems we can not get the results synchronously.
So how to implement this kind of feature?
function main () {
var v = 0, k;
for (k in obj)
v += calc(obj[k].formula)
return v;
}
function calc (formula) {
var result = 0;
if (formula.type === 'SQL') {
var someSql = "select value from x = y"; // this SQL related to the formula;
client.query(someSql, function (err, rows) {
console.log(rows[0].value);
// *How can I get the value here?*
});
result = ? // *How can I return this value to the main function?*
}
else
result = formulaCalc(formula); // some other asyn code
return result;
}
Its not possible to return the result of an asynchronous function, it will just return in its own function scope.
Also this is not possible, the result will always be unchanged (null)
client.query(someSql, function (err, rows) {
result = rows[0].value;
});
return result;
Put a callback in the calc() function as second parameter and call that function in the client.query callback with the result
function main() {
calc(formula,function(rows) {
console.log(rows) // this is the result
});
}
function calc(formula,callback) {
client.query(query,function(err,rows) {
callback(rows);
});
}
Now if you want the main to return that result, you also have to put a callback parameter in the main and call that function like before.
I advice you to check out async its a great library to not have to deal with this kind of hassle
Here is a very crude way of implementing a loop to perform a calculation (emulating an asynchronous database call) by using events.
As Brmm alluded, once you go async you have to go async all the way. The code below is just a sample for you to get an idea of what the process in theory should look like. There are several libraries that make handling the sync process for asynch calls much cleaner that you would want to look into as well:
var events = require('events');
var eventEmitter = new events.EventEmitter();
var total = 0;
var count = 0;
var keys = [];
// Loop through the items
calculatePrice = function(keys) {
for (var i = 0; i < keys.length; i++) {
key = keys[i];
eventEmitter.emit('getPriceFromDb', {key: key, count: keys.length});
};
}
// Get the price for a single item (from a DB or whatever)
getPriceFromDb = function(data) {
console.log('fetching price for item: ' + data.key);
// mimic an async db call
setTimeout( function() {
price = data.key * 10;
eventEmitter.emit('aggregatePrice', {key: data.key, price: price, count: data.count});
}, 500);
}
// Agregate the price and figures out if we are done
aggregatePrice = function(data) {
count++;
total += data.price;
console.log('price $' + price + ' total so far $' + total);
var areWeDone = (count == data.count);
if (areWeDone) {
eventEmitter.emit('done', {key: data.key, total: total});
}
}
// We are done.
displayTotal = function(data) {
console.log('total $ ' + data.total);
}
// Wire up the events
eventEmitter.on('getPriceFromDb', getPriceFromDb);
eventEmitter.on('aggregatePrice', aggregatePrice);
eventEmitter.on('done', displayTotal);
// Kick of the calculate process over an array of keys
keys = [1, 2, 3]
calculatePrice(keys);