SweetFeet
SweetFeet

Reputation: 91

setTimeout will not delay

I was recently making a timer object and a ticking function that would tick every second according to a setTimeout loop. However, there was no delay in the ticking. If you try out the below code, you will find that the time number has increased to the thousands in only a few seconds. What, if anything, am I doing wrong?

<html>

<head>

</head>
    <button onclick="startTimer()">Start</button>
    <button onclick="stopTimer()">Stop Timer</button>
    <button onclick="readTimer()">Read Timer</button>

    <script>
function tick(){
    console.log("TICK TOCK");
    if(this.running == true){
        this.time += 1;
        console.log("HELLO!");
        setTimeout(this.tick(), 1000, $(this));
    }

}

function start(){
    this.running = true;
    this.tick();
}
function read(){
    return this.time;
}
function stop(){
    this.running = false;
}

function reset(){
    if(this.running == false){
        this.time = 0;
    }else {
        this.time = 0;
    } 
    this.tick();
}
function timer(){
    this.running = false;
    this.time = 0;
    this.start = start;
    this.read = read;
    this.stop = stop;
    this.reset = reset;
    this.tick = tick;
}
var t = new timer();

        function startTimer(){
            t.start();
        }   
        function stopTimer(){
            t.stop();
        }
        function readTimer(){
            alert("This is the current Timer Reading: " + t.time);
        }





    </script>
</html>

Upvotes: 0

Views: 163

Answers (3)

trincot
trincot

Reputation: 351369

You are passing an executed function, instead of a function reference to setTimeout. To pass the function itself, remove the parentheses. Secondly, to make sure this will still be the current this when tick is eventually invoked, use .bind(this).

Note that the third argument of setTimeout would pass that value to tick, which is of no use in your case. NB: That $(this) is probably a remnant of some other code, since the $ would be typically used with jQuery, which you are not using.

So taking that all together, do:

setTimeout(this.tick.bind(this), 1000)

Upvotes: 1

Felix Guo
Felix Guo

Reputation: 2708

Your error is that you call setTimeOut on this.tick(). When you call this inside the tick() function, you are already referring to the tick function, so you want to use setTimeout(this, 1000); and your timer will work properly.

See this fiddle for solution: https://jsfiddle.net/sg7yf6r4/

Read more about the issue: Javascript objects calling function from itself

Upvotes: 1

Wayne Allen
Wayne Allen

Reputation: 1745

The first parameter of setTimeout should be a function. However, you are passing it the result of a function. So instead of setTimeout(this.tick(), 1000, $(this)); you should use setTimeout(this.tick, 1000, $(this));.

Upvotes: 1

Related Questions