即使调用了clearInterval,interval也会继续激发

interval keeps firing even though clearInterval has been called

本文关键字:继续 interval 调用 clearInterval      更新时间:2023-09-26

我正试图让一个函数运行10次,每次运行之间都有一个停顿,但当我尝试运行时,它会无限次重复该函数,然后在10次之后暂停,以此类推。现在,这是有问题的代码:

for(i=0;i<10;i++) {
    console.log(i);
    interval = setInterval(function() {console.log("Function ran");}, 1000);
}
window.clearInterval(interval);

控制台:
0
1
2
3
4
5
6
7
8
9
运行的功能

["运行的功能"在"9"后无限次重复]

interval = setInterval(function() {console.log("Function ran");}, 1000);

此行每次都会创建一个新的间隔实例,这意味着您已经创建了10个间隔。在循环结束时,interval保存创建的最后一个间隔的id。因此,这是你正在清理的唯一一个,其他的仍在运行。

要取消间隔,您需要跟踪函数被调用的次数。你可以这样做的一种方法如下:

function pauseAndRepeat(delay, iterations, func) {
    var i = 0;
    var interval = setInterval(function() {
        func();
        if(++i === iterations) {
            clearInterval(interval);
        }
    }, delay);    
}

这里我们有一个函数,它在本地作用域中定义了一个计数器(i)。然后,它使用一个函数创建一个间隔,该函数检查计数器,看看它是否应该调用您的函数(func),或者在完成后清除间隔。interval将在实际调用间隔处理程序时设置。在这种情况下,处理程序基本上是一个闭包,因为它绑定到pauseAndRepeat的本地作用域。

然后您可以调用如下函数:

pauseAndRepeat(1000, 10, function() {
    console.log("Function ran");
});

这将打印Function ran十次,每次暂停一秒钟。

setInterval预计将在一段时间内永远运行。每次你在这里调用setInterval,你会有一个新的无限循环每10秒运行一次你的函数,正如其他人所指出的,你只是取消了最后一个循环。

使用链式setTimeout调用可能会做得更好:

var counter = 0;
function next() {
    if (counter < 10) {
        counter++;
        setTimeout(function() {
            console.log("Function ran");
            next();
        }, 1000);
    }
}
next();

这会链接延迟的函数,在每次运行后为下一个函数设置超时。您可以对setInterval和取消进行类似的操作:

var counter = 0;
var intervalId = setInterval(function() {
    console.log("Function ran");
    if (++counter >= 10) {
        clearInterval(intervalId);
    }
}, 1000);

在这两种情况下,关键问题是在回调函数中触发下一次运行或取消间隔,而不是在同步代码中。