[英]Javascript setTimeout unexpected output
我一直在使用在我的应用程序中使用setInterval(fn,delay)函数的脚本,在阅读了setTimeout和JS如何工作后,我遇到了一些奇怪的结果,所以我做了一个测试:这是jsfiddle https:// jsfiddle。净/ jyq46uu1 / 2 /
和建议的代码:
var limit = 1000000000;
var intervals = 0;
var totalTime = new Date();
var startTime = new Date();
var uid = setInterval(
function () {
// final lap?
if (intervals == 9) clearInterval(uid);
for (i = 0; i < limit; i += 1) {
// just working the CPU
}
// reduce the iterations
limit = limit / 10;
intervals += 1;
console.log('Interval ' + intervals +' Time elapsed : ' + (new Date() - startTime));
// reset the time
startTime = new Date();
}, 250, 9);
好吧,从我的红色http://ejohn.org/blog/how-javascript-timers-work/ Javascript使得计时器调用setInterval中的函数,即使“线程被阻塞”,所以如果函数仍在执行调用只是排队等等等...在我的笔记本中代码生成这个:
"Interval 1 Time elapsed : 4264"
"Interval 2 Time elapsed : 477"
"Interval 3 Time elapsed : 91"
"Interval 4 Time elapsed : 170"
"Interval 5 Time elapsed : 246"
"Interval 6 Time elapsed : 242"
"Interval 7 Time elapsed : 248"
"Interval 8 Time elapsed : 248"
"Interval 9 Time elapsed : 248"
好吧,如果我的红色是真的,到第一个间隔完成时,所有函数调用都在队列中...在我的脚本中我减少了每次执行的工作,所以每个调用应该花费的时间少于前一个,但无论我设置多少迭代,经过的时间总是在第四次运行后获得间隔速度。 也许我弄错了但是如果到4264时所有功能都已经在队列中并且假设立即运行,那么它们应该显示更少的时间,对吧? ...如果第3次迭代显示91而其他人只是落后,则应该取91或更少。 但这种情况并非如此。
如果你了解发生了什么,请向我解释,因为我觉得我错过了什么。
我认为第一次不是从队列中的初始间隔计算,而是从设置startTime的点开始计算。
然后第一个计时器计算初始化时间,环境创建,变量和计时器分配。
试试这个修改:
var limit = 1000000000;
var intervals = 0;
var totalTime = new Date();
var startTime = false;
var uid = setInterval(
function () {
if (!startTime) startTime = new Date();
// final lap?
if (intervals == 9) clearInterval(uid);
for (i = 0; i < limit; i += 1) {
// just working the CPU
}
// reduce the iterations
limit = limit / 10;
intervals += 1;
console.log('Interval ' + intervals +' Time elapsed : ' + (new Date() - startTime));
// reset the time
startTime = new Date();
}, 250, 9);
此外,第一次需要更长的时间可能是因为函数被解释,然后后续时间被Javascript JIT“编译”/优化(参见https://en.wikipedia.org/wiki/Just-in-time_compilation) )。 查看此代码以查看证明
var limit = 1000000000;
var intervals = 0;
var totalTime = new Date();
var startTime = new Date();
var uid = setInterval(
function () {
startTime = new Date();
// final lap?
if (intervals == 9) clearInterval(uid);
for (i = 0; i < limit; i += 1) {
// just working the CPU
}
// reduce the iterations
limit = limit / 10;
intervals += 1;
console.log('Interval ' + intervals +' Time elapsed : ' + (new Date() - startTime));
// reset the time
startTime = new Date();
}, 250, 9);
输出:
Interval 1 Time elapsed : 3249
Interval 2 Time elapsed : 299
Interval 3 Time elapsed : 31
Interval 4 Time elapsed : 5
Interval 5 Time elapsed : 0
Interval 6 Time elapsed : 0
Interval 7 Time elapsed : 0
Interval 8 Time elapsed : 0
Interval 9 Time elapsed : 0
Interval 10 Time elapsed : 0
setInterval不能很好地衡量它应该排队下一次执行的时间。 我认为这与sleep()有关。 如果一个进程正在占用cpu并将其挂起(就像你所做的那样),这是不可靠的。
setInterval仅保证:
setInterval不保证某些执行将在未来确定的时间之前发生。 这取决于当前的CPU使用率。
排队和启动排队功能还取决于当前的CPU使用情况。
额外的通用建议如果你需要定期执行一个函数,我建议这种方法可以确保执行之间的延迟总是超过250毫秒
var t = false;
var fun = function() {
console.log("run");
t = setTimeout(fun, 250);
}
fun();
我不确定我是对的,这是我所知道的“Javascript”。
Javascript基于基于事件的触发,并且“没有队列和等待”。 它将同时进行(类似于线程)。
我想这会有意义,因为它解释和接受下一个的速度有多快。
好吧,我有一些要点,先看看结果。
“新”代码:
var limit = 1000000000;
var intervals = 0;
var totalTime = new Date();
top.uid = setInterval(
function () {
startTime = new Date();
// final lap?
if (intervals == 9) clearInterval(top.uid);
for (i = 0; i < limit; i += 1) {
// just working the CPU
}
// reduce the iterations
limit = limit / 10;
intervals += 1;
console.log('Interval ' + intervals +' Time elapsed : ' + (new Date() - startTime));
// reset the time
}, 1);
请注意,我从第4行删除变量startTime并将其传递给函数的开头,因此,计算出的时间与所有调用相同。 我将TIMER格式更改为250毫秒到1毫秒,因此您无需从每个结果计算-250毫秒。
新的结果非常一致,并且显示计算的时间花费现在非常可靠和连贯。
希望我帮助清除它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.