javascript是一个单线程语言,只有一个主线程在程序中运行,如果有io请求,是浏览器的线程池(注意:浏览器是多线程的)去处理,等结果放回(把回调放回到主线程的执行队列中,并不能马上执行),回到主线程中去处理,所以javascript可以给人一种多线程的感觉。
所以基于上述条件,像setInterval(func, 0)和setTimeout(func, 0)这样的语句,也不没有马上执行他,而是放到执行队列的后面,执行完前面的队列,才轮到setInterval和setTimeout。
而setInterval(func, 100)也是一样的,在100毫秒后,把func放到队列的后面,并没有在100毫秒后马上执行他,所以引出题目的讨论。
如下代码:
var interval = 0;
var self = this;
var startTime = new Date().getTime();
var count = 0;
var callback2 = function() {
count++;
var offset = new Date().getTime() - (startTime + count * 100);
var nextTime = 100 - offset;
if (nextTime < 0) {
nextTime = 0;
}
for (var i=0; i<=1000000000; i++) {
}
console.log(offset);
}
window.setInterval(callback2, 100);
如果在setInterval的回调里,需要执行代码的时间比较长,比如循环百万千万次;或者就算你写的代码很完美,效率很高,但是只要用户把浏览器压后台、切换网页标签等让浏览器不显示的操作,都会让上述代码出现下面的结果:
结果是:每次都会延迟几百毫秒,且会叠加。
对于上述问题的解决方法是:
var callback = function() {
count++;
var offset = new Date().getTime() - (startTime + count * 1000);
var nextTime = 1000 - offset;
if (nextTime < 0) {
nextTime = 0;
}
for (var i=0; i<=1000000000; i++) {
}
console.log(offset);
setTimeout(callback, nextTime);
}
interval = window.setTimeout(callback, 1000);
通过 当前时间的判断,将每次延迟的时间在下次执行的时候矫正回来。
上述代码执行的结果是:
结果:每次执行还是会有延迟,但是不会叠加。