最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - JS - How to correctly use setTimeout() - Stack Overflow

programmeradmin1浏览0评论

So I have this function that executes on setTimeout and console.log returns the correct value for the variable I named time however the function is running with no delay when I run the code. The code is server side for a game I am making. The code is supposed to gradually restore health to the player after using an item. My issue is with the settimeout function... also it works when I use it in the browser but not from my node console.

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

So I have this function that executes on setTimeout and console.log returns the correct value for the variable I named time however the function is running with no delay when I run the code. The code is server side for a game I am making. The code is supposed to gradually restore health to the player after using an item. My issue is with the settimeout function... also it works when I use it in the browser but not from my node console.

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);
}
Share Improve this question edited Sep 30, 2016 at 11:49 Ricardo Rodrigues 1337 bronze badges asked Jul 5, 2012 at 22:05 ShawnShawn 9112 gold badges12 silver badges23 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 6

The problem is here:

setTimeout(balm(i),time);

What that does is call balm and feed its return value in to setTimeout, which isn't what you want. You want to pass setTimeout a function that, when called, will call balm with a given i value. You do that like this:

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

That way, the balm function gets called later, and gets called with the i value as of when the timeout was scheduled. Without the makeHandler thing, all balm instances would see i as it was when they ran (e.g., they'd all see -1). This is because in JavaScript, a closure has enduring access to the variables in context; not a copy of them when the the closure was created. So all of them see the current value of i. (More: Closures are not plicated)

(Note that on NodeJS — the environment you're using — and also on Firefox, you can use the non-standard extension to setTimeout that allows you to give arguments to pass to the function; see pksunkara's answer. But for anyone looking to do this client-side on the web [rather than server-side with Node], beware, that is not standard.)

To illustrate this, here's an example (this one runs in a browser, but it's the same for server-side stuff like 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

Here's the output:

show (wrong): 5
show (wrong): 5
show (wrong): 5
show (wrong): 5
show (wrong): 5
show (right): 0
show (right): 1
show (right): 2
show (right): 3
show (right): 4

This is the correct usage of setTimeout

setTimeout(balm, time, i);

You have to pass a function, then delay, and then args to the aforementioned function

发布评论

评论列表(0)

  1. 暂无评论