据我所知,这两个javascript的行为方式相同:
选项A:
function myTimeoutFunction()
{
doStuff();
setTimeout(myTimeoutFunction, 1000);
}
myTimeoutFunction();
选项B:
function myTimeoutFunction()
{
doStuff();
}
myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);
使用setTimeout和setInterval之间有什么区别吗?
他们本质上试图做同样的事情,但setInterval方法将比setTimeout方法更准确,因为setTimeout等待1000ms,运行函数,然后设置另一个超时。因此,等待时间实际上比1000毫秒多一点(如果您的函数需要很长时间才能执行,则会更长)。
虽然有人可能认为setInterval将每1000ms执行一次,但需要注意的是,setInterval也会延迟,因为JavaScript不是一种多线程语言,这意味着,如果脚本的其他部分正在运行,则该间隔必须等待它完成。
在这个Fiddle中,您可以清楚地看到超时将落后,而时间间隔几乎一直都是1次/秒(脚本正在尝试这样做)。如果将顶部的速度变量更改为20这样的小值(意味着它将尝试每秒运行50次),则间隔将永远不会达到每秒50次迭代的平均值。
延迟几乎总是可以忽略不计的,但是如果你正在编程一些非常精确的东西,你应该使用一个自动调整的计时器(它本质上是一个基于超时的计时器,它会根据创建的延迟不断调整自己)
setInterval可以更容易地取消代码的未来执行。如果使用setTimeout,则必须跟踪计时器id,以防以后取消它。
var timerId = null;
function myTimeoutFunction()
{
doStuff();
timerId = setTimeout(myTimeoutFunction, 1000);
}
myTimeoutFunction();
// later on...
clearTimeout(timerId);
对
function myTimeoutFunction()
{
doStuff();
}
myTimeoutFunction();
var timerId = setInterval(myTimeoutFunction, 1000);
// later on...
clearInterval(timerId);
setInterval和setTimeout都返回一个计时器id,您可以使用它来取消执行,即在触发超时之前。要取消,请调用clearInterval或clearTimeout,如下所示:
var timeoutId = setTimeout(someFunction, 1000);
clearTimeout(timeoutId);
var intervalId = setInterval(someFunction, 1000),
clearInterval(intervalId);
此外,当您离开页面或关闭浏览器窗口时,超时会自动取消。
有什么不同吗?
对在调用setTimeout()后,Timeout会执行一定的时间;Interval在上一个激发的间隔之后执行一定的时间。
如果doStuff()函数需要一段时间才能执行,则会注意到差异。例如,如果我们用.表示对setTimeout/setInterval的调用。,使用*触发超时/间隔,使用[--]执行JavaScript代码,时间线如下:
Timeout:
. * . * . * . * .
[--] [--] [--] [--]
Interval:
. * * * * * *
[--] [--] [--] [--] [--] [--]
下一个复杂的问题是,如果JavaScript已经在忙着做某件事(例如处理上一个间隔)时触发了一个间隔。在这种情况下,间隔将被记住,并且在上一个处理程序完成并将控制权返回给浏览器时立即发生。例如,对于有时短([-])有时长([--])的doStuff()进程:
. * * • * • * *
[-] [-----][-][-----][-][-] [-]
•表示无法立即执行代码的间隔激发,而是被挂起。
因此,间隔时间尽量“赶上”进度。但是,它们不会一个一个地排队:每个间隔只能有一个执行等待。(如果他们都排队,浏览器将留下一个不断扩大的未执行列表!)
. * • • x • • x
[------][------][------][------]
x表示无法执行或挂起的间隔激发,因此被丢弃。
如果你的doStuff()函数习惯性地需要比为它设置的时间间隔更长的时间来执行,那么浏览器将消耗100%的CPU来服务它,并且可能会变得反应迟钝。
你用哪种?为什么?
链接超时为浏览器提供了一个保证的空闲时间;Interval试图确保它正在运行的功能尽可能接近其计划时间执行,而牺牲了浏览器UI的可用性。
我会考虑一次性动画的时间间隔,我希望它尽可能流畅,而链式超时对于加载页面时一直在进行的动画更为礼貌。对于要求较低的用途(例如每30秒启动一次微不足道的更新程序),您可以安全地使用其中之一。
就浏览器兼容性而言,setTimeout早于setInterval,但您现在遇到的所有浏览器都支持两者。多年来最后一个掉队的是WinMo<6.5版本的IE Mobile,但希望这也已经过时了。
我对setInterval(func,milisec)进行了简单的测试,因为我很好奇当函数时间消耗大于间隔持续时间时会发生什么。
setInterval通常会在上一次迭代开始之后安排下一次迭代,除非函数仍在运行。如果是,setInterval将等待,直到函数结束。一旦发生,函数就会立即再次启动——不需要根据计划等待下一次迭代(因为在没有时间超过函数的情况下)。并行迭代也没有运行的情况。
我已经在Chrome v23上测试过了。我希望它在所有现代浏览器中都是确定性的实现。
window.setInterval(function(start) {
console.log('fired: ' + (new Date().getTime() - start));
wait();
}, 1000, new Date().getTime());
控制台输出:
fired: 1000 + ~2500 ajax call -.
fired: 3522 <------------------'
fired: 6032
fired: 8540
fired: 11048
wait函数只是一个线程阻塞助手-同步ajax调用,在服务器端需要2500毫秒的处理时间:
function wait() {
$.ajax({
url: "...",
async: false
});
}
setInterval()
setInterval()是一种基于时间间隔的代码执行方法,它具有在达到时间间隔时重复运行指定脚本的本机能力。脚本作者不应将其嵌套到回调函数中以使其循环,因为默认情况下它会循环。除非您调用clearInterval(),否则它将在间隔时间内继续激发。
如果您想为动画或时钟周期循环代码,请使用setInterval()。
function doStuff() {
alert("run your code here when time interval is reached");
}
var myTimer = setInterval(doStuff, 5000);
setTimeout()
setTimeout()是一种基于时间的代码执行方法,当达到时间间隔时,只执行一次脚本。除非您将setTimeout()对象嵌套在要运行的函数内,使其循环脚本,否则它不会再次重复。如果调整为循环,除非调用clearTimeout(),否则它将在间隔时间内继续发射。
function doStuff() {
alert("run your code here when time interval is reached");
}
var myTimer = setTimeout(doStuff, 5000);
如果您希望某件事在指定的时间段后发生一次,请使用setTimeout()。这是因为它只在达到指定间隔时执行一次。
您的代码将具有不同的执行间隔,在某些项目中,例如在线游戏,这是不可接受的。首先,您应该怎么做,以使代码在相同的整数下工作,您应该将“myTimeoutFunction”更改为:
function myTimeoutFunction()
{
setTimeout(myTimeoutFunction, 1000);
doStuff();
}
myTimeoutFunction()
此更改后,它将等于
function myTimeoutFunction()
{
doStuff();
}
myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);
但是,您仍然不会得到稳定的结果,因为JS是单线程的。目前,如果JS线程将忙于某些事情,它将无法执行回调函数,并且执行将延迟2-3毫秒。您是否每秒执行60次,并且每次您有1-3秒的随机延迟,这是绝对不可接受的(一分钟后,大约会有7200毫秒的延迟),我可以建议您使用类似的方法:
function Timer(clb, timeout) {
this.clb = clb;
this.timeout = timeout;
this.stopTimeout = null;
this.precision = -1;
}
Timer.prototype.start = function() {
var me = this;
var now = new Date();
if(me.precision === -1) {
me.precision = now.getTime();
}
me.stopTimeout = setTimeout(function(){
me.start()
}, me.precision - now.getTime() + me.timeout);
me.precision += me.timeout;
me.clb();
};
Timer.prototype.stop = function() {
clearTimeout(this.stopTimeout);
this.precision = -1;
};
function myTimeoutFunction()
{
doStuff();
}
var timer = new Timer(myTimeoutFunction, 1000);
timer.start();
此代码将保证稳定的执行周期。即使线程也会很忙,您的代码将在1005毫秒后执行,下次它将有995毫秒的超时,结果将是稳定的。
选项A和选项B看起来工作相同的原因主要是因为setInterval和setTimeout函数的位置不同。
function myTimeoutFunction()
{
doStuff();
setTimeout(myTimeoutFunction, 1000);
}
myTimeoutFunction();
这是一个递归函数,如果doStuff非常复杂,则setTimeout必须跟踪setTimout的所有调用以及当前的doStuff,这会使它变得更慢,而且速度更快。
function myTimeoutFunction()
{
doStuff();
}
myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);
另一方面,setInterval只需要跟踪上一个setInterval和当前的doStuff,使其保持恒定的速度。
So which one should you use?
从上面的内容中,您应该能够得出结论,更好的方法是setInterval。