假设您想使用 setTimeout 创建一个 java 函数,以便它每 5 秒重复一次。这个定时函数只是更新一些数据。当用户单击打开覆盖层的按钮时会发生调用,并且只要覆盖层打开,该函数就会继续运行。一旦覆盖层关闭,abandonUpdate 就会设置为 true,并在计时器函数中检查这一点。但是,如果用户在超时完成之前打开叠加层,它将添加超时函数的另一个实例。
如何避免这种情况?
(顺便说一句,计时器似乎无法在 jsfiddle 或 bin 上工作。但是相同的代码在我的服务器上工作......)
var abandonUpdate = true;
function timers(){
if(!abandonUpdate){
$('.timeout').css({"background-color":'#'+(Math.random()*0xFFFFFF<<0).toString(16)});
setTimeout("timers()", 5000);
}
}
$('.timeout').click(function(){
abandonUpdate = false;
console.log("Hello I'm running");
timers();
});
最佳答案
让我们看一个直接的演示:
var loops = 0,
to = setTimeout(function test(){
console.log('Test run ' + ++loops + ' times.');
if (loops < 100) {
to = setTimeout(test, 3000);
}
}, 3000),
check = setTimeout(function check(){
console.log('Test checked (' + loops + ').');
if (loops > 10) {
console.log('Test setTimeout aborted.');
clearTimeout(to);
return;
}
setTimeout(check, 500);
});
我们这里有两个重新生成的setTimeout()
,每个函数的作用都略有不同。第一个,使用 var to
运行 test()
函数,这就是我们试图抢占(或中止,如果你愿意的话)的函数。
第二个,var check
,运行得更频繁(1/2 秒而不是 3 秒)。第二个是监视 test()
的迭代,并使用捕获的引用 var to< 来“取消”(或“清除”)
。 test()
超时。/
请注意,当它重新生成超时时,我如何在 test()
中捕获引用?如果你不这样做,你就会陷入无限循环; setTimeout()
返回的每个引用都会发生变化,因此您必须小心捕获对两个函数都可以访问的同一变量的引用。否则,您将“清除”可能/可能已经结束的超时。
当然,另一种选择是使用 setInterval()
,它在运行时始终使用相同的引用,因此 clearInterval(to)
可以工作,您不必担心将 to
设置为正确的引用。我认为这是优先的;此处使用 setInterval()
,而不是 setTimeout()
。有时重生是有意义的,但我认为在这里没有意义。
var intl;
function timers() {
$('.timeout').css({
"background-color": '#' + (Math.random() * 0xFFFFFF << 0).toString(16)
});
}
$('.timeout').click(function(){
if (intl) {
clearInterval(intl);
console.log("I stopped goodbye!");
intl = 0;
} else {
console.log("Hello I'm running!");
intl = setInterval(timers, 5000); // Pass the test reference, not "test()";
}
});
关于javascript - 如何退出超时函数的实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25006255/