简体   繁体   中英

setTimeout executes faster than simultaneous setInterval

So, I have a setInterval and a setTimeout running simultaneously in this click-o-meter thing I'm doing: the user enters an specified number of seconds he/she wants the game to run for, and then it counts how many clicks you have done, what was the average time between each click, and the average amount of clicks per second you've made during the specified period of time.

<html>
    <head></head>
    <body>
        <input type='text' id='timerInput'></input>
        <button id='btn'>Click</button>
        <script>
            var before;
            var now;
            var clicks = 0;
            var cts = 0; //Stands for 'Clicks This Second'
            var intervals = new Array();
            var cps = new Array();
            var cpsCounter;
            var timer;
            var canContinue = true;
            var timerInput = document.getElementById('timerInput');
            var timerTime;
            var wasBad = false;

            document.getElementById('btn').onclick = function() {
                if(canContinue) {
                    if(clicks <= 0) {
                        if(timerInput.value.replace(/\D/, '') === timerInput.value) {
                            wasBad = false;
                            timerTime = parseInt(timerInput.value.replace(/\D/, '')) * 1000;
                            before = new Date();
                            cpsCounter = window.setInterval(ctsFunction, 1000);
                            timer = window.setTimeout(finish, timerTime);
                        }else{
                            alert('Only numbers please!');
                            wasBad = true;

                        }

                    }else{
                        now = new Date();
                        console.log(now - before);
                        intervals.push(now - before);
                        before = new Date();
                    }
                    if(!wasBad){
                        clicks++;
                        cts++;
                    }
                }else{console.log('Game ended');}
            };

            function ctsFunction() {
                console.log('Clicks this second: ' + cts);
                cps.push(cts);
                cts = 0;
            }

            function finish() {
                console.log('Clicks: ' + clicks);
                console.log('Average Speed (ms): ' + Math.floor(intervals.reduce(function(a, b){return a + b;}) / (clicks - 1)));
                console.log('Average Speed (clicks per second): ' + (cps.reduce(function(a, b){return a + b;}) / cps.length));
                intervals = new Array();
                console.log('cps.length: ' + cps.length);
                cps = new Array();
                clicks = 0;
                cts = 0;
                window.clearInterval(cpsCounter);
                canContinue = false;
            }
        </script>
    </body>
</html>

So, the problem is that when the gmae finishes, that is, when timer reaches the end, ctsFunction() is supposed to run once more at the last second, so it can register data from it; but finish() is executed faster, or prior to ctsFunction() , thus clearing the cpsCounter interval and not allowing it to do anything on the last second. I've tried adding some extra milliseconds to timer , but if you choose to run the game for enough seconds, the same problem will eventually happen (eg if you add 1ms, the problem will be solved for up to 2 seconds, but not for more).

I have a setInterval and a setTimeout running simultaneously

It will never happens because javascript is a single thread language. There is no matter what is in your code, javascript can't execute two commands simultaneously.

And one more:

timer delay is not guaranteed. JavaScript in a browser executes on a single thread asynchronous events (such as mouse clicks and timers) are only run when there's been an opening in the execution.

Read this article to understand how javascript timers work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM