[英]setInterval (javaScript): are there known bugs?
100次中99次,这完美地运作:
function a(){
setInterval("b()",1000);
updateText("still working");
}
function b(){
timer++;
updateText(timer);
}
偶尔第一个循环等待20秒到2分钟。 此后它完美运行。 我知道计时器可以在Android手机上暂停(当显示软键盘时)。 还有其他条件可能延迟setInterval吗?
首先,强烈建议你提供一个回调( function
)作为第一个参数而不是字符串,因为该字符串是在全局范围内计算的,我们都知道当我们在js中使用eval
时会发生不好的事情(相关的eval post: 什么时候JavaScript的eval()不是邪恶的? )。
所以,你的
setInterval("b()", 1000);
应改写为:
setInterval(b, 1000);
要么:
setInterval(function() { b(); }, 1000);
我还建议您使用setTimeout
来模拟setInterval
。
setInterval
函数的主要缺点是它每n
毫秒执行一段代码,而不管前一代码块的执行情况如何。
因此,如果由于某种原因, setInterval
回调的执行时间比提供的延迟要长,则会导致一些堆栈溢出 。
我们以下面的代码为例:
function foo() {
// this takes about 2 seconds to execute
// .. code here
}
setInterval(foo, 1000);
这实际上将冻结浏览器,因为它将执行foo
(几乎)无限次,但它永远不会完成它。
在这种情况下的解决方案是使用setTimeout
模拟setInterval
,以确保在再次调用之前回调已完成执行:
function foo() {
// this takes about 2 seconds to execute
// .. code here
}
function newSetInterval(callback, duration, callbackArguments) {
callback.apply(this, callbackArguments);
var args = arguments,
scope = this;
setTimeout(function() {
newSetInterval.apply(scope, args);
}, duration);
}
newSetInterval(foo, 1000);
现在,只有在前一个实例完成代码执行后才会再次调用foo
。
我会对你的代码应用相同的东西,以便让浏览器决定何时可以执行代码,而不是强迫它执行代码块,因为它在那个时刻是忙碌的:
function a() {
newSetInterval(b, 1000);
updateText("still working");
}
function b() {
timer++;
updateText(timer);
}
function newSetInterval(callback, duration, callbackArguments) {
callback.apply(this, callbackArguments);
var args = arguments,
scope=this;
setTimeout(function() {
newSetInterval.apply(scope, args);
}, duration);
}
如果您感兴趣,我已经重写了setInterval
和clearInterval
函数,以便在任何地方使用它们,而不需要处理堆栈溢出:
function setInterval(f, time) {
setInterval.ids = setInterval.ids || {};
setInterval.idCount = setInterval.idCount || 0;
var that = this,
id = setInterval.idCount++,
// to prevent firefox bug that adds an extra element to the arguments
l = arguments.length - 2;
(function theFn() {
// to prevent firefox bug that adds an extra element to the arguments
var args = [].slice.call(arguments, 0, l);
f.apply(this, args);
setInterval.ids[id] = setTimeout.apply(this, [theFn, time].concat(args));
}).apply(that, [].slice.call(arguments, 2, arguments.length));
return id;
}
function clearInterval(id) {
if(!setInterval.ids || !setInterval.ids[id]) {
return false;
}
clearTimeout(setInterval.ids[id]);
return true;
}
尝试这个,
setInterval(b, 1000);
要么
setInterval(function(){
timer++;
updateText(timer);
}, 1000);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.