0

所以我有这个在 setTimeout 上执行的函数,console.log 返回我命名为 time 的变量的正确值,但是当我运行代码时,该函数正在运行,没有延迟。该代码是我正在制作的游戏的服务器端。该代码应该在使用物品后逐渐恢复玩家的健康。我的问题是 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;
        }
    });
}
for (i=30;i>=0;i--){
   time=(31-i)*1000;
   console.log(time);
   setTimeout(balm(i),time);
}
4

2 回答 2

6

问题在这里:

setTimeout(balm(i),time);

这样做是调用 balm并将其返回值提供给setTimeout,这不是您想要的。您想传递setTimeout一个函数,该函数在调用时将balm使用给定i值调用。你这样做:

setTimeout(makeHandler(i),time);
function makeHandler(index) {
    return function() {
        balm(index);
    };
}

这样,该balm函数会在稍后被调用,并使用i超时被调度时的值调用。如果没有这个makeHandler东西,所有balm实例在运行i时都会看到它们的样子(例如,它们都会看到)。这是因为在 JavaScript 中,闭包可以持久访问上下文中的变量。创建闭包时不是它们的副本。所以他们都看到了 的当前值。(更多:闭包并不复杂-1i

(请注意,在 NodeJS(您正在使用的环境)以及 Firefox 上,您可以使用非标准扩展来setTimeout允许您将参数传递给函数;请参阅pksunkara 的回答。但对于任何想要这样做的人Web 上的客户端 [而不是使用 Node 的服务器端],请注意,这不是标准的。)

为了说明这一点,这里有一个例子(这个例子在浏览器中运行,但对于像 NodeJS 这样的服务器端的东西也是一样的):

(function() {

  // Wrong
  setTimeout(function() {
    var i;

    for (i = 0; i < 5; ++i) {
      setTimeout(function() {
        show("wrong", i);
      }, i * 50);
    }
  }, 0);

  // Right
  setTimeout(function() {
    var i;

    for (i = 0; i < 5; ++i) {
      setTimeout(makeHandler(i), i * 50);
    }

    function makeHandler(index) {
      return function() {
        show("right", index);
      };
    }
  }, 500);

  function show(marker, val) {
    display("show (" + marker + "): " + val);
  }

  function display(msg) {
    var p = document.createElement('p');
    p.innerHTML = String(msg);
    document.body.appendChild(p);
  }
})();

现场复制| 来源

这是输出:

显示(错误):5
显示(错误):5
显示(错误):5
显示(错误):5
显示(错误):5
显示(右):0
显示(右):1
显示(右):2
显示(右):3
显示(右):4
于 2012-07-05T22:10:11.027 回答
5

这是setTimeout的正确用法

setTimeout(balm, time, i);

您必须传递一个函数,然后是延迟,然后是 args 到上述函数

于 2012-07-05T22:10:02.150 回答