Multiple timeouts not working?

Posted on
  • So I'm still enjoying to work on my fruitmachine, but the way I implement multiple timeouts don't seem to work correctly.
    Basically, I've 3 LED's, or fruits - or wheels, and I stop them one by one in order of time. When I spin the wheel, I tell it when to stop spinning. It works by just setting the velocity of the wheel to 0.

    Wheel.prototype.spin = function(stopt) // stopt = stoptime
    {
      this.vel = (2 + Math.random() * 5) / 40; // give the wheel a velocity
      setTimeout(this.stop, stopt); // tell it when to stop
    };
    

    Then you have the stop function

    Wheel.prototype.stop = function()
    {
      this.vel = 0.0;
    };
    

    The spinning happens when the user clicks the button. At that time, spin is called(not Wheel.spin)

    function spin()
    {
      for (var i = 0; i < N_LEDS;) // loop trough all wheels, spin them
      {
        wheels[i].spin((++i * 500));
      }
      
      setTimeout(function(){
         //... other code. It checks some win conditions and lights and stuff after every wheel stopped.
      }, (N_LEDS + 2.5) * 500);
    

    But, only the last setTimeout seems to be called.
    What am I doing wrong?

    Here's the full code.

  • Well, one guess is that (like in a browser) setTimeout(); doesn't set the this variable to what you'd expect, so when stop is called from setTimeout(this.stop, stopt); and it tries to do this.vel = 0, it's actually setting vel on the global variable, not on your wheel.

    To fix it, try:

    Wheel.prototype.spin = function(stopt) // stopt = stoptime
    {
      this.vel = (2 + Math.random() * 5) / 40; // give the wheel a velocity
      var wheel = this;
      setTimeout(function() {
        wheel.stop();
      }, stopt); // tell it when to stop
    };
    

    There are other ways to do it, but that one is probably the most readable.

  • Just to add that this is pretty much standard JS. For example:

    function Foo(x) { this.baz = x; }
    Foo.prototype.bar = function() { return this.baz; };
    
    var f = new Foo("Hello World");
    console.log(f.bar());  // prints "Hello World"
    function printer(fn) { console.log(fn()); }
    printer(f.bar); // prints 'undefined'
    
  • Thanks a lot! I often forget those kinds of things. Now it works!

  • @Gordon, didn't you recently add .bind()? Would that now be even a better option - resource-wise - and for sure from a point of avoiding globals...?

    I guess the code would then look like this:

    Wheel.prototype.spin = function(stopt) // stopt = stoptime
    {
      this.vel = (2 + Math.random() * 5) / 40; // give the wheel a velocity
      setTimeout(this.stop.bind(this), stopt); // tell it when to stop
    };
    

    Adding this .bind() was a great move! Still have to get used to it having started JS with 1.3...

  • Yes, that works too - and as you say it's more efficient.

    It's just that it's not very readable if you don't know what bind does :)

  • ...not because I say it, it is because you @Gordon made it so! - Credit where - to whom - credit is due!

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Multiple timeouts not working?

Posted by Avatar for joppiesaus @joppiesaus

Actions