在使用javascript时我注意到了这件事。你可以使用
var i=0;
var startingTime=new Date().getTime();
setInterval("foo()",1);
function foo() {
i+=1;
if ($("#foodiv").text()==i) {
//we detected a doubled value (parallel execution)
$("#repdiv").append("[repetition on "+i+"]");
}
$("#foodiv").html(i);
$("#timediv").html(Math.floor((new Date().getTime()-startingTime)/1000));
}
但是当我阅读并尝试自己时,时间不是1毫秒,它至少是10毫秒或者其他东西。事实上,在10秒后,我的值大约为2300/2400,而不是预期的10000.
这是程序的最小可能时间因素???肯定没有。如果我试试这个:
<html><head>
<script language="javascript" type="text/javascript" src="jquery-1.4.min.js"></script>
<script type="text/javascript">
var i=0;
var startingTime=new Date().getTime();
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1);
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1);
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1);
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1);
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1);
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1);
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1);
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1);
function foo() {
i+=1;
if ($("#foodiv").text()==i) {
//we detected a doubled value (parallel execution)
$("#repdiv").append("[repetition on "+i+"]");
}
$("#foodiv").html(i);
$("#timediv").html(Math.floor((new Date().getTime()-startingTime)/1000));
}
</script>
</head>
<body>
<div id="foodiv"></div> (counter)
<br/>
<div id="timediv"></div> (seconds passed)
<br/>
<div id="repdiv"></div>
<br/>
</body>
</html>
计数器将非常快,10秒后,我的值为12000 !!!!这对我来说是无法解释的,因为调用不是并行执行的(或者至少我们可以为不同的调用设置一些加倍的i值,在repdiv div中计算)。
有人可以解释一下吗?我知道cpu在所有这些调用中都非常紧张,但至少它会令人惊讶地加快速度。
我在论坛中阅读了你的所有回复和其他任务,他们证实了我的想法。但真正的问题是为什么!当我可以进行多次顺序调用以获得更低的时间时,为什么他们将限制设置为15ms?我敢肯定这个多回调系统并不是一个好习惯,但我可以做到,而且我可能会使cpu负载饱和。
答案 0 :(得分:8)
不,Javascript是单线程的。运行setInterval
或setTimeout
时,会生成一个事件,然后将其添加到浏览器的执行队列中。因此,虽然您无法保证代码本身在您希望它运行时完全运行,但您可以确保每次生成事件时都会生成该事件。因此,在这种情况下,您生成的12个事件彼此非常接近。我注意到您已使用1
作为间隔值。但是,大多数浏览器中的最小值大约为15
(有关详细信息,请参阅here。)浏览器将按照它们在执行队列中的顺序运行事件(在setInterval
中,事件试图追赶。看看Marcel链接的答案,更多细节)。
这意味着在第一个场景中,您每隔15毫秒就会生成一个事件。因此计数器增加得更慢。但在第二种情况下,你有十二个事件,这些事件每隔15毫秒就会相互接近,因此计数器的增量会快得多。
答案 1 :(得分:2)
在大多数浏览器中,JavaScript计时器值设置为至少15毫秒,即使给出的值较小。 AFAIK只有谷歌Chrome使用4毫秒。另请参阅How to determine the best "framerate" (setInterval delay) to use in a JavaScript animation loop?的接受答案。
答案 2 :(得分:1)
不,JavaScript没有多线程,至少现在没有。
请阅读this answer,了解setInterval
的工作原理。
答案 3 :(得分:1)
您发布的代码未运行,此处是更正后的代码:
var i=0;
setInterval(foo,1);
function foo() {
i+=1;
if ($("#foodiv").text()==i) {
//we detected a doubled value (parallel execution)
$("#repdiv").append("[repetition on "+i+"]");
}
$("#foodiv").html(i);
}
如果在代码运行时查看CPU性能,您会发现它几乎没有工作,这意味着较低的速率不是由于代码繁忙。它根本不会按照你的要求频繁发射间隔。
(如果你开始十二个时间间隔,负载仍然很难显示。我开始了200个间隔,然后在其中一个核心上接近100%的负载。)
浏览器使用某种时钟来确定应该触发的时间间隔,并且该时钟通常具有比毫秒更低的分辨率。因此,间隔将不会再次触发,直到下一个时钟滴答,在您的情况下似乎相隔约15毫秒。
答案 4 :(得分:0)
传递给setInterval
方法的第二个值确实是最小值。虽然1代表1毫秒,但大多数浏览器不太可能给你这个超时。另一个答案是它更可能在15毫秒左右。
即使如此,第二项是最小值,也可以解释第一个样本。
此行为也解释了第二个样本。您调用的每个setInterval
方法都会注册一个完全独立的回调。它们各自至少有1但彼此没有依赖关系。所以它们在相同的1毫秒间隔内发射是完全有效的(只要每个间隔在重新发射之前等待1毫秒)。