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),…
You can’t use a loop variable
ideclared 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:
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.