即使已调用 clearInterval,interval 仍会触发

interval keeps firing even though clearInterval has been called

我试图让一个函数达到 运行 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
函数运行

["Function ran"在“9”之后重复无限次]

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

这一行每次都会创建一个新的interval-instance,这意味着您已经创建了 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 将在实际调用 interval-handler 时设置。在这种情况下,处理程序基本上是一个闭包,因为它绑定到 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);

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