Javascript - 多个 setInterval 时 clearInterval 不起作用

Posted

技术标签:

【中文标题】Javascript - 多个 setInterval 时 clearInterval 不起作用【英文标题】:Javascript - clearInterval not working when multiple setInterval 【发布时间】:2016-11-04 16:32:25 【问题描述】:

我遇到了 setInterval 和 clearInterval 的问题。 在我的代码中,我设置了多个间隔,当计数减少到 0 时,停止执行。

如下:

<!DOCTYPE html>
<html>
    <head>
        <meta name="viewport" content="initial-scale=1.0" charset="utf-8">
    </head>
    <body>
    <body>
        <script type="text/javascript">
            for (var i=0; i<4; i++)
                var count = 100;

                var IntervalID = window.setInterval((function() // closure
                    var timeoutID = IntervalID; // temp
                    var countTemp = count; // temp
                    var id = i;

                    return function()
                        countTemp --;
                        console.log(id + " " + countTemp);

                        // do something here

                        if ( countTemp == 0 )                                  
                            clearInterval(timeoutID); // stop the execution
                            console.log(id + " stop");
                        
                    
                )(), 20);
               
        </script>
    </body>
</html>

控制台出现停止消息“x stop”后,除最后一个元素(id:3)外,所有元素都停止,它还在继续。

我尝试以另一种形式编写我的代码:

<!DOCTYPE html>
<html>
    <head>
        <meta name="viewport" content="initial-scale=1.0" charset="utf-8">
    </head>
    <body>
        <script type="text/javascript">
            for (var i=0; i<4; i++)
                doSomething(i);
            

            function doSomething(id)
                var count = 100;

                var IntervalID = window.setInterval((function() // closure
                    var timeoutID = IntervalID; // temp
                    var countTemp = count; // temp

                    return function()
                        countTemp --;
                        console.log(id + " " + countTemp);

                        // do something here

                        if ( countTemp == 0 )                                  
                            clearInterval(timeoutID); // stop the execution
                            console.log(id + " stop");
                        
                    
                )(), 20);
            
        </script>
    </body>
</html>  

但这一次,所有元素都不会停止。

我有两个问题: 1. 这两个代码有什么区别? 2.如何让代码正常工作?

编辑: 如果只是想让代码正常工作,只需要在第二个sn-p中改一行:

clearInterval(timeoutID); // stop the execution  

clearInterval(IntervalID); // stop the execution  

但是其他人的回答可以解决我在这个问题上的困惑。

【问题讨论】:

您尝试使用 IntervalID-s 时的值是多少? Console.log 那一项,就在 var timeoutID = IntervalID; 的下方; 在第一个 sn-p 中,timeoutID 未定义 i==0,因为对 setInterval 的调用尚未完成。因此,在var timeoutID = IntervalID; // temp 上方添加console.log(i + " - " + IntervalID); 将显示0 - undefined,然后是1 - 12 - 23 - 3 哦,我明白了一部分,在第一个sn-p中,当countTemp减少到0时,clearInterval(timeoutID);实际上停止了前一个(在id==1部分,它停止id==0执行; id==2 stop id==1; 等等。但是没有一个停止id==3,所以它还在继续)。 【参考方案1】:

问题是闭包中没有捕获正确的 IntervalID,当你的闭包运行时,window.setInterval 还没有返回 id,因为赋值表达式还没有完成。

一个简单的技巧可以用于对象,因为它们在 JavaScript 中通过引用传递给函数

我已经修改了循环来完成这个

for (var i=0; i < 4; i++)

    var count = 100;

    var args =  id: i, counter: count ;
    var IntervalID = window.setInterval((function(args) // closure

        return function()
            args.counter--;
            console.log(args.id + " " + args.counter)
            if ( args.counter == 0 )                                  
                clearInterval(args.IntervalID); // stop the execution
                console.log(args.id + " stop");
            
        .bind(args);
    )(args), 20);

    // by now the correct IntervalID will be captured
    // as the assignment expression has finished executing
    args.IntervalID = IntervalID; 

【讨论】:

谢谢,现在我明白了。回答我自己的问题 1,在第一个 sn-p 中,timeoutID 捕获保留在内存中的前一个 IntervalID,所以只有最后一个不能停止。在第二个sn-p中,调用一个函数,完成后从函数栈中弹出,所以timeoutID不能捕获任何值,是undefined,所有元素/间隔都不能停止。

以上是关于Javascript - 多个 setInterval 时 clearInterval 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

mobile-safari javascript:多个 setTimeouts 或 setIntervals

多个 setIntervals 同时运行的问题

setInterval如何在结束后返回执行结果?

(转)如何实现同一浏览器多个标签页之间的通信——cookie+setInterval

如何用javascript连续点击多个按钮?

setInterval 中的 Javascript 函数