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

问题描述 投票:0回答:1

我正在编写 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 循环。

我尝试使用下面的这个函数来定位我认为会在 forEach 循环中标记为 strumTimeout 的所有 setTimeout。但这不起作用,因为它摆脱了页面上的所有 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 都会打印出越来越多的“删除超时”字符串

我也尝试过使用常规的 for 循环和中断,但它要么不起作用,要么说“跳转目标不能跨越函数边界”,这取决于我把它放在哪里。

如果有一种方法可以标记由 forEach 循环创建的 setTimeouts 并以某种方式清除或删除它们,这就是我正在寻找的。但是,如果有更好的方法让动画在可变超时时间或间隔时间的序列中播放,我也很想听听。

javascript arrays css-animations settimeout
1个回答
0
投票

您可以使用

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));
© www.soinside.com 2019 - 2024. All rights reserved.