javascript 如何为forEach循环中的所有超时运行clearTimeout?

icomxhvb  于 2023-03-11  发布在  Java
关注(0)|答案(1)|浏览(163)

我正在编写Javascript来播放一系列重复的动画,这些动画会转到浏览器中播放的歌曲的音符。下面是我目前使用的代码:

//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);
    });
}

然而,我希望能够在用户关掉音乐时清除所有这些超时,我能够通过在strum()周围添加if语句来使乱弹动画停止;函数,但它并没有阻止forEach循环在数组中运行,如果我在数组完成之前再次播放动画,它会变得非常抖动,因为它同时运行了两个forEach循环。
我尝试使用下面的这个函数来定位所有的setTimeouts,我认为这些setTimeouts会在forEach循环中被标记为strumTimeout。但是这个函数不起作用,因为它会删除页面上的所有setTimeout函数,而我需要运行其他的setTimeout函数来在不同的点停止其他的动画。

//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
    }
}

此外,每当我激活console.log时,它都会打印出越来越多的“removing timeout”字符串
我也尝试过使用一个常规的for循环和一个break,但是它要么不起作用,要么说“跳转目标不能跨越函数边界”,这取决于我把它放在哪里。
如果有一种方法可以标记forEach循环创建的setTimeouts并以某种方式清除或删除它们,这就是我正在寻找的。但是,如果有一种更好的方法可以让动画以可变超时时间或间隔时间的顺序播放,我也很好奇。

flseospp

flseospp1#

您可以使用Array#map从循环中获取一个数组中的所有超时ID,以便稍后清除。

// 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));

相关问题