Chr*_*thy 2 javascript delay setinterval
100次中99次,这完美地运作:
function a(){
setInterval("b()",1000);
updateText("still working");
}
function b(){
timer++;
updateText(timer);
}
Run Code Online (Sandbox Code Playgroud)
偶尔第一个循环等待20秒到2分钟.此后它完美运行.我知道计时器可以在Android手机上暂停(当显示软键盘时).还有其他条件可能延迟setInterval吗?
gio*_*_13 10
首先,强烈建议你提供一个callback(function)作为第一个参数而不是字符串,因为该字符串是在全局范围内计算的,我们都知道当我们eval在js中使用时会发生坏事(相关的eval post: When is is JavaScript的eval()不是邪恶的吗?).
所以,你的
setInterval("b()", 1000);
Run Code Online (Sandbox Code Playgroud)
应改写为:
setInterval(b, 1000);
Run Code Online (Sandbox Code Playgroud)
要么:
setInterval(function() { b(); }, 1000);
Run Code Online (Sandbox Code Playgroud)
我还建议你setTimeout用来模拟一个setInterval.
该setInterval函数的主要缺点是它每n毫秒执行一段代码,而不管前一代码块的执行情况如何.
因此,如果由于某种原因,setInterval回调的执行时间比提供的延迟要长,则会导致一些堆栈溢出.
我们以下面的代码为例:
function foo() {
// this takes about 2 seconds to execute
// .. code here
}
setInterval(foo, 1000);
Run Code Online (Sandbox Code Playgroud)
这实际上会冻结浏览器,因为它将执行foo(几乎)无限次,但它永远不会完成它.
在这种情况下的解决方案是模拟setIntervalwith setTimeout,以确保在再次调用之前回调已完成执行:
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);
Run Code Online (Sandbox Code Playgroud)
现在,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);
}
Run Code Online (Sandbox Code Playgroud)
如果你有兴趣,我已经重写了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;
}
Run Code Online (Sandbox Code Playgroud)