0

コードは必要以上に複雑に見えるかもしれません。 i を balm 関数に渡したいのですが、間違っているため undefined が返されます。
追加情報: これは、私が書いているゲームのサーバー用です。ノードのコンソールで実行しています。

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);
}

これは、概念を示す単純化されたバージョンです

for (i=3;i>=0;i--){
   setTimeout(function foo(i){
      console.log(foo)
   },1000*i);

1000 ミリ秒後に「1」、2000 ミリ秒後に「2」、3000 ミリ秒後に「3」という出力が期待できます。 、...

4

3 に答える 3

2

コールバック関数の外で宣言されたループ変数を使用することはできませんi。コールバックが実際に実行されると、正しい値を持つことを期待できます。代わりに、最後の値が割り当てられます。

以下のコードは、最も単純な (ただし最短ではない) ソリューションを示しています。

function showNumber(n) {
    return function() {
        console.log(n);
    }
}

for (i = 3; i >= 0; i--) {
     setTimeout(showNumber(i), 1000 * i);
}

つまり、(ループ変数にパラメーターが「バインド」されている) 関数を呼び出し、関数によって実際に呼び出された別の関数を返しますsetTimeout()

@Xanderの回答に示されているように、通常はすぐに呼び出される関数式を使用してこれを行う方法は他にもありますが、上記のコードは解決策をうまく示しています。

于 2012-07-05T21:11:06.723 に答える
1

i0最初のコールバックが実行され、残りの呼び出しまでそのままである場合です。

i宣言の時点での値をキャプチャするクロージャーを作成できます。

for (i = 3; i >= 0; i--){
    function(x) {
        setTimeout(function foo(i){
            console.log(i)
        },1000 * x);
    })(i);
}
于 2012-07-05T21:12:23.907 に答える
0

関数の宣言で変数を関数に渡すことはできません。

    for (i=3; i>=0; i--) {
        fooLoop(i);
    }

    function fooLoop(iterator) {
        setTimeout(function () {
            console.log("value of i is" + iterator);
        }, 1000*iterator);
    }
于 2012-07-05T21:14:14.200 に答える