Reputation: 911
The code might look more complicated than it needs to be I want to pass i into the balm function but it returns undefined because I'm doing it wrong.
Just extra information: This is for the server of a game I'm writing. Running in console for node.
for (i=30;i>=0;i--){
setTimeout(function balm(i){
this_sql ="UPDATE game_moblist SET hp = least(max_hp, hp +"+Math.round(i/2)+") WHERE id ="+mobid
connection.query(this_sql, function(err, rows, fields) {if (err) err=null});
console.log(this_sql)
this_sql ="SELECT hp, max_hp FROM game_moblist WHERE id ="+mobid; //emite catch all update pointint to hp..
connection.query(this_sql, function(err, rows, fields) {if (err) throw err;
socket.emit ('updatemisc',handler,rows);//eval handler using args
if (rows[0].hp==rows[0].max_hp){
i=0;
return i;
}
});
},(31-i)*333);
}
here is a simplified version just showing the concept
for (i=3;i>=0;i--){
setTimeout(function foo(i){
console.log(foo)
},1000*i);
I would expect the following output "1" after 1000 ms "2" after 2000 ms "3" after 3000 ms EDIT: It worked when I defined the function outside of setTimeout() and then called it like this setTimeout(balm(i),...
Upvotes: 0
Views: 76
Reputation: 35407
i
is 0
when the first callback executes and stays that way through the rest of the calls.
You could create a closure to capture the value of i
at the moment of declaration:
for (i = 3; i >= 0; i--){
function(x) {
setTimeout(function foo(i){
console.log(i)
},1000 * x);
})(i);
}
Upvotes: 1
Reputation: 6034
Variables can not be passed into a function in its declaration.
for (i=3; i>=0; i--) {
fooLoop(i);
}
function fooLoop(iterator) {
setTimeout(function () {
console.log("value of i is" + iterator);
}, 1000*iterator);
}
Upvotes: 0
Reputation: 340055
You can't use a loop variable i
declared outside the callback function and expect it to have the right value once the callback is actually executed - it'll have the last value assigned to it instead.
The code below shows the simplest (but not the shortest) solution:
function showNumber(n) {
return function() {
console.log(n);
}
}
for (i = 3; i >= 0; i--) {
setTimeout(showNumber(i), 1000 * i);
}
In other words, you call a function (that has its parameter "bound" to your loop variable) which then returns another function that is the one actually invoked by setTimeout()
.
There are other ways of doing this, typically with an Immediately Invoked Function Expression as shown in @Xander's answer, but the code above demonstrates the solution nicely.
Upvotes: 2