Shawn
Shawn

Reputation: 911

I'm passing a variable to a function incorrectly and don't see my mistake

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

Answers (3)

Alex
Alex

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

Austin
Austin

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

Alnitak
Alnitak

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

Related Questions