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

发布于 2024-09-10 20:20:14 字数 1149 浏览 6 评论 0原文

我使用 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);

没有这个怎么能做到呢?有更好的办法吗?

I'm using jQuery to setup a timer or interval loop on a few elements to check them every couple seconds. I've tried setting a timer and checking if I should restart it, or setting and interval and checking if I should stop it.

Although simplified, this is basically what I need:

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]);
    }
}

The ID's for class items are id_1, id_2, id_3. But I simply get 3 alerts all giving id_3. In my code I started off trying to pass 'this', but kept simplifying it to figure out the issue.

How can I get it to copy the variable to a new address each time? I know I need to use closures. It seems to be referencing the other var no mater what.

I tried simplifying it to a loop with timers like so:

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

But I think I'm just making my problem worse and that doesn't seem to do anything.

I've searched for previous questions, but most are filled with tons of extra code rather than cutting it down the the specific issue and are solved in some other manner.
I'd like to understand how this works better by getting this example working. I did manage, while writing this, to figure out I can set off the timer with a helping function.

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

How can this be done without that? Is there some better way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

少年亿悲伤 2024-09-17 20:20:14

将变量“myID”设置为匿名函数的本地变量,

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

Have variable 'myID' local to the anonymous function,

var myID = $(this).attr('id');
吃→可爱长大的 2024-09-17 20:20:14

当你使用each时,你就处于闭包中,你只是忘记了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]);
    }
}

You're in a closure when you use each, you just have forgotten var to make your variable private in the function scope

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]);
    }
}
旧时模样 2024-09-17 20:20:14

那么您想每三秒对每个匹配的元素运行一次 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 所说,您将 var 保留在 myID 的声明中,这意味着它是全局的,并且每次迭代都会被覆盖。结果是,当 setInterval 调用 myFunction 而不是通过闭包获取唯一的本地 myID 时,您会得到已经被覆盖的全局 ID umpty次。

So you want to run myFunction on each of the matched elements every three seconds?

Try this:

$('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 );
        }
    }
};

If the condition in something() is met you're done, if not the function schedules itself to run again in 3 seconds with the same element as before. You can call this as many times as you want on different elements, each call has its own elem.

I prefer to pass objects like elem around and delay working with their internals until the last possible moment. Let something() worry about the id or whatever.

None of the other gymnastics with the associative array (instead of new Array() you could just use {}), or clearInterval, or ID's are necessary.

To actually address your solution, as Marimuthu said, you left var off the declaration of myID, which means its global and it gets overwritten each iteration. The result is that when setInterval invokes myFunction instead of getting a unique local myID via closure, you get the global one that has already been overwritten umpty times.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文