Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How do I run clearTimeout for all timeouts inside a forEach loop?

I’m writing Javascript to play a series of repeated animations that go to the notes of a song that plays in the browser. Here is the code I currently have that works:

//Determine the timing for each note played
var expTimes = [0, 215, 323, 645, 860, 968, 1290...]
var strumTimeout;


//Loop through the array and strum at each listed timeout through the duration of the audio

function StrumPattern(strumArray){

//Toggles the CSS transforms to make the strum animation happen 
    function strum(){
        if (strumHand.style.transform == "rotate(50deg)"){
            strumHand.style.transform = "rotate(0deg)";
        }else{
            strumHand.style.transform = "rotate(50deg)";
        }
    }  
   
//Sets the timeout for each strum animation to play in a sequence
    strumArray.forEach(delay => { 
            strumTimeout = setTimeout(() => {
            strum();
            console.log("strum");
        }, delay);
    });
}

However, I want to be able to clear all these timeouts when the user turns off the music. I was able to make the strumming animation stop by adding an if statement around the strum(); function, but it does not stop the forEach loop from running through the array, and if I play the animation again before the array completes, it gets all jittery because it is running two forEach loops at the same time.

I tried using this function below to target all the setTimeouts that I thought would be labeled strumTimeout from the forEach loop. This does not work though, as it gets rid of ALL setTimeout functions on the page, when I have other setTimeout functions that need to run to stop other animations at different points.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

//Clears
function clearStrum(){
    var id = strumTimeout;

    while (id--) {
        console.log('removing timeout');
        window.clearTimeout(id); // will do nothing if no timeout with id is present
    }
}

Furthermore, the console.log prints out an increasing number of ‘removing timeout’ strings each time I activate it

I have also tried using a regular for loop and a break, but it either did not work or it said "Jump target cannot cross function boundary," depending on where I put it.

If there is a way to label the setTimeouts created by the forEach loop and clear or remove them somehow, that is what I am looking for. However, if there is a better way to get animations to play in a sequence with variable timeout times or interval times, I’m curious to hear as well.

>Solution :

You can use Array#map to get all the timeout ids from the loop in an array to be cleared later.

// outside the function
let timeouts;
// inside the function, replace strumArray.forEach with the following:
timeouts = strumArray.map(delay => setTimeout(() => {
    strum();
    console.log("strum");
}, delay));
// cancel all those timeouts later:
timeouts?.forEach(id => clearTimeout(id));
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading