使用闭包在循环中创建的javascript计时器或间隔

时间:2010-07-20 20:28:33

标签: javascript loops timer closures setinterval

我正在使用jQuery在几个元素上设置定时器或间隔循环,以便每隔几秒检查一次。我已经尝试设置一个计时器并检查是否应该重新启动它,或者设置和间隔并检查是否应该停止它。

虽然简化了,但这基本上就是我所需要的:

var mytimers = new Array();
$('div.items').each(function() {
    myID = $(this).attr('id');
    mytimers[myID] = setInterval( function() { myFunction(myID) } , 3000)
});
function myFunction(param) {
    alert(param);
    if (something()) {
        clearInterval(mytimers[param]);
    }
}

课程项目的ID为id_1,id_2,id_3。但我只得到3个提醒id_3。在我的代码中,我开始尝试传递'this',但一直在简化它以找出问题。

我怎样才能让它每次都将变量复制到新地址?我知道我需要使用闭包。它似乎引用了其他变量无关。

我尝试将它简化为一个带有定时器的循环:

function tester(item) {
    return function() {
        alert(item);
    };
}
for(x=1;x<=3;x++) {
    setTimeout( '(function() { tester(x) })(x)' , 3000);
}

但我认为我只是让我的问题变得更糟,而且似乎没有做任何事情。

我已经搜索过以前的问题,但大多数都填充了大量的额外代码,而不是削减特定问题,并以其他方式解决。 通过让这个例子有效,我想了解这是如何工作的。在写这篇文章的过程中,我确实设法了解了我可以通过帮助功能来启动计时器。

function tester(item)
    alert(item);
function myTimer(item)
    setInterval( function() { tester(item); }, 3000);
for(x=1;x<=3;x++)
    myTimer(item);

如果没有这个怎么办呢?还有更好的方法吗?

3 个答案:

答案 0 :(得分:4)

将变量'myID'置于匿名函数

的本地
var myID = $(this).attr('id');

答案 1 :(得分:3)

当你使用每一个时,你处于一个闭包中,你只是忘记了var,使你的变量在函数范围内变为私有

var mytimers = new Array();
$('div.items').each(function() {
    **var** myID = $(this).attr('id'); 
    mytimers[myID] = setInterval( function() { myFunction(myID) } , 3000)
});
function myFunction(param) {
    alert(param);
    if (something()) {
        clearInterval(mytimers[param]);
    }
}

答案 2 :(得分:1)

所以你想每隔三秒在每个匹配的元素上运行myFunction吗?

试试这个:

$('div.items').each( myFunction(this) );

var myFunction = function(elem) {
    return function() {
        if ( something(elem) ) {
            //return or do something with elem
        } else {
            window.setTimeout( myFunction(elem), 3000 );
        }
    }
};

如果满足something()中的条件,则表示已完成,否则该函数会自行安排在3秒内使用与之前相同的元素再次运行。您可以根据需要多次调用此元素,每个调用都有自己的elem

我更喜欢传递像elem这样的物体并延迟使用它们的内部物体,直到最后一刻。让something()担心id或其他。

没有其他具有关联数组的体操(而不是new Array()你只能使用{}),或者clearInterval或ID都是必需的。

要实际解决您的解决方案,正如Marimuthu所说,您将varmyID的声明中删除,这意味着它的全局并且每次迭代都会被覆盖。结果是,当setInterval调用myFunction而不是通过闭包获得唯一的本地myID时,您将获得已被覆盖多次的全局变量。