【问题标题】:JS - How to correctly use setTimeout()JS - 如何正确使用 setTimeout()
【发布时间】:2012-07-05 22:05:35
【问题描述】:

所以我有这个在 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);
}

【问题讨论】:

    标签: javascript node.js


    【解决方案1】:

    问题出在这里:

    setTimeout(balm(i),time);
    

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

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

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

    (请注意,在 NodeJS(您正在使用的环境)以及 Firefox 上,您可以使用 setTimeoutnon-standard 扩展,它允许您将参数传递给函数;请参阅 pksunkara's answer。但对于希望在 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);
      }
    })();
    

    Live copy | source

    这是输出:

    显示(错误):5
    显示(错误):5
    显示(错误):5
    显示(错误):5
    显示(错误):5
    显示(右):0
    显示(右):1
    显示(右):2
    显示(右):3
    显示(右):4

    【讨论】:

    • 这里的编辑很棒。 i 不是您每次传递的值,而是在函数实际运行时最终成为的值,这并不完全明显。你的makeHandler 解决了这个问题。如果可以的话,我会再次 +1 这个答案...
    【解决方案2】:

    这是setTimeout的正确用法

    setTimeout(balm, time, i);
    

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

    【讨论】:

    • 需要注意的是,这在 NodeJS(和 Firefox)中是正确的。将其他参数传递给setTimeout 的能力不是跨环境的标准功能,并且在客户端不起作用。不过NodeJS supports it是真的,所以+1。
    • @user1481372:恕我直言,我的回答有效。但绝对,pksunkara 的答案在您使用的环境中效果很好。
    • T.J. Crowder 很好地描述了 setTimeout 的工作原理。 @user1481372,你应该读一下。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-08
    • 2021-03-28
    • 1970-01-01
    相关资源
    最近更新 更多