javascriptsettimeoutsetintervalclearintervalcleartimeout

ClearInterval not working (vanilla javascript)


Here's the setup. I'm looking to stop the looper (setInterval()) from running after 5 seconds.

I have lots of comments so it should be fairly easy to understand, just ask me any questions for clarification.

I have tried moving the if statement (that checks the timer value === 5000) around. Tried it inside the setInterval function, tried in the onClick function.

I have also tried running setInterval() and clearInterval() prefixed with window.

Any ideas folks? 🙏🏼 🥺

window.onload = function() {
    var looper;
    var degrees = 0;
    var timer = 0; // timer used to monitor how long the wheel has been spinning

    function startWheelAnimation(elementId, speed) {
        // 1. get the element to rotate
        const ele = document.getElementById(elementId); // get the HTML element to rotate
        const cssRotateVal = "rotate("+degrees+"deg)"; // the CSS style rotate value
        
        // 2. CSS3 browser compatibility checks
        if (navigator.userAgent.match("Chrome")) {
            ele.style.WebkitTransform = cssRotateVal;
        } else if(navigator.userAgent.match("Firefox")){
            ele.style.MozTransform = cssRotateVal;
        } else if(navigator.userAgent.match("MSIE")){
            ele.style.msTransform = cssRotateVal;
        } else if(navigator.userAgent.match("Opera")){
            ele.style.OTransform = cssRotateVal;
        } else {
            ele.style.transform = cssRotateVal;
        }
        
        // 3. start looping at the rate of speed var
        looper = setInterval( ()=>{
            // at the rate of speed var run the following code
            startWheelAnimation( elementId, speed );
        }, 
        speed);
        
        degrees++; // increment the degrees value by 1
        timer++; // increment the timer value by 1
        console.log(timer); // devtool

        if (degrees > 359) { // reset the degrees value back to 0 upon a full rotation
            degrees = 0;
            clearInterval(looper); // stop the wheel spinning
        }

        if (timer === 5000) { // after 5 seconds has passed reset the timer and stop the looper
                console.log(looper);
                timer = 0;
                clearInterval(looper); // stop the wheel spinning
            }
    }
    document.getElementById('spinButton').addEventListener("click", event => {
        const speed = 100;
        startWheelAnimation("wheel", speed);
    });
}

Solution

  • You should not create a new setTimerInterval in each execution of the function. This will accumulate different active intervals, and you'll only have the reference to the last one you created.

    Instead move that piece of code out of the function, and place it in the event handler you have as addEventListener call back:

    document.getElementById('spinButton').addEventListener("click", event => {
        const speed = 100;
        const elementid = "wheel";
        // schedule the repeated run:
        looper = setInterval( ()=>{
            // at the rate of speed var run the following code
            startWheelAnimation(elementid, speed );
        }, 
        speed);
        // also run it immediately
        startWheelAnimation(elementid, speed);
    });